diff --git a/app/utils/ghost-paths.js b/app/utils/ghost-paths.js index 944b30152..ce7251d5e 100644 --- a/app/utils/ghost-paths.js +++ b/app/utils/ghost-paths.js @@ -18,7 +18,7 @@ export default function () { let subdir = path.substr(0, path.search('/ghost/')); let adminRoot = `${subdir}/ghost/`; let assetRoot = `${subdir}/ghost/assets/`; - let apiRoot = `${subdir}/ghost/api/v3/admin`; + let apiRoot = `${subdir}/ghost/api/canary/admin`; function assetUrl(src) { return subdir + src; diff --git a/mirage/config.js b/mirage/config.js index 763930c69..8c641e723 100644 --- a/mirage/config.js +++ b/mirage/config.js @@ -1,3 +1,4 @@ +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import mockApiKeys from './config/api-keys'; import mockAuthentication from './config/authentication'; import mockConfig from './config/config'; @@ -26,8 +27,7 @@ export default function () { // _must_ be called before the namespace property is set this.passthrough('/ghost/assets/**'); - // this.urlPrefix = ''; // make this `http://localhost:8080`, for example, if your API is on a different server - this.namespace = '/ghost/api/v3/admin'; // make this `api`, for example, if your API is namespaced + this.namespace = ghostPaths().apiRoot; this.timing = 1000; // delay for each request, automatically set to 0 during testing this.logging = true; @@ -49,8 +49,7 @@ export default function () { // Mock all endpoints here as there is no real API during testing export function testConfig() { - // this.urlPrefix = ''; // make this `http://localhost:8080`, for example, if your API is on a different server - this.namespace = '/ghost/api/v3/admin'; // make this `api`, for example, if your API is namespaced + this.namespace = ghostPaths().apiRoot; // this.timing = 400; // delay for each request, automatically set to 0 during testing this.logging = false; diff --git a/tests/integration/adapters/tag-test.js b/tests/integration/adapters/tag-test.js index 16c4a1999..c7c944a33 100644 --- a/tests/integration/adapters/tag-test.js +++ b/tests/integration/adapters/tag-test.js @@ -1,4 +1,5 @@ import Pretender from 'pretender'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import {describe, it} from 'mocha'; import {expect} from 'chai'; import {setupTest} from 'ember-mocha'; @@ -18,7 +19,7 @@ describe('Integration: Adapter: tag', function () { }); it('loads tags from regular endpoint when all are fetched', function (done) { - server.get('/ghost/api/v3/admin/tags/', function () { + server.get(`${ghostPaths().apiRoot}/tags/`, function () { return [200, {'Content-Type': 'application/json'}, JSON.stringify({tags: [ { id: 1, @@ -40,7 +41,7 @@ describe('Integration: Adapter: tag', function () { }); it('loads tag from slug endpoint when single tag is queried and slug is passed in', function (done) { - server.get('/ghost/api/v3/admin/tags/slug/tag-1/', function () { + server.get(`${ghostPaths().apiRoot}/tags/slug/tag-1/`, function () { return [200, {'Content-Type': 'application/json'}, JSON.stringify({tags: [ { id: 1, diff --git a/tests/integration/adapters/user-test.js b/tests/integration/adapters/user-test.js index 1402e9355..cfe0ae830 100644 --- a/tests/integration/adapters/user-test.js +++ b/tests/integration/adapters/user-test.js @@ -1,4 +1,5 @@ import Pretender from 'pretender'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import {describe, it} from 'mocha'; import {expect} from 'chai'; import {setupTest} from 'ember-mocha'; @@ -18,7 +19,7 @@ describe('Integration: Adapter: user', function () { }); it('loads users from regular endpoint when all are fetched', function (done) { - server.get('/ghost/api/v3/admin/users/', function () { + server.get(`${ghostPaths().apiRoot}/users/`, function () { return [200, {'Content-Type': 'application/json'}, JSON.stringify({users: [ { id: 1, @@ -40,7 +41,7 @@ describe('Integration: Adapter: user', function () { }); it('loads user from slug endpoint when single user is queried and slug is passed in', function (done) { - server.get('/ghost/api/v3/admin/users/slug/user-1/', function () { + server.get(`${ghostPaths().apiRoot}/users/slug/user-1/`, function () { return [200, {'Content-Type': 'application/json'}, JSON.stringify({users: [ { id: 1, @@ -58,7 +59,7 @@ describe('Integration: Adapter: user', function () { }); it('handles "include" parameter when querying single user via slug', function (done) { - server.get('/ghost/api/v3/admin/users/slug/user-1/', (request) => { + server.get(`${ghostPaths().apiRoot}/users/slug/user-1/`, (request) => { let params = request.queryParams; expect(params.include, 'include query').to.equal('roles,count.posts'); diff --git a/tests/integration/components/gh-file-uploader-test.js b/tests/integration/components/gh-file-uploader-test.js index 25c3746b6..62b84d5bc 100644 --- a/tests/integration/components/gh-file-uploader-test.js +++ b/tests/integration/components/gh-file-uploader-test.js @@ -1,6 +1,7 @@ import $ from 'jquery'; import Pretender from 'pretender'; import Service from '@ember/service'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import hbs from 'htmlbars-inline-precompile'; import sinon from 'sinon'; import {UnsupportedMediaTypeError} from 'ghost-admin/services/ajax'; @@ -18,13 +19,13 @@ const notificationsStub = Service.extend({ }); const stubSuccessfulUpload = function (server, delay = 0) { - server.post('/ghost/api/v3/admin/images/', function () { + server.post(`${ghostPaths().apiRoot}/images/`, function () { return [200, {'Content-Type': 'application/json'}, '{"url":"/content/images/test.png"}']; }, delay); }; const stubFailedUpload = function (server, code, error, delay = 0) { - server.post('/ghost/api/v3/admin/images/', function () { + server.post(`${ghostPaths().apiRoot}/images/`, function () { return [code, {'Content-Type': 'application/json'}, JSON.stringify({ errors: [{ type: error, @@ -41,7 +42,7 @@ describe('Integration: Component: gh-file-uploader', function () { beforeEach(function () { server = new Pretender(); - this.set('uploadUrl', '/ghost/api/v3/admin/images/'); + this.set('uploadUrl', `${ghostPaths().apiRoot}/images/`); this.owner.register('service:notifications', notificationsStub); }); @@ -86,7 +87,7 @@ describe('Integration: Component: gh-file-uploader', function () { await fileUpload('input[type="file"]', ['test'], {name: 'test.csv'}); expect(server.handledRequests.length).to.equal(1); - expect(server.handledRequests[0].url).to.equal('/ghost/api/v3/admin/images/'); + expect(server.handledRequests[0].url).to.equal(`${ghostPaths().apiRoot}/images/`); }); it('fires uploadSuccess action on successful upload', async function () { @@ -185,7 +186,7 @@ describe('Integration: Component: gh-file-uploader', function () { }); it('handles file too large error directly from the web server', async function () { - server.post('/ghost/api/v3/admin/images/', function () { + server.post(`${ghostPaths().apiRoot}/images/`, function () { return [413, {}, '']; }); await render(hbs`{{gh-file-uploader url=uploadUrl}}`); @@ -205,7 +206,7 @@ describe('Integration: Component: gh-file-uploader', function () { }); it('handles unknown failure', async function () { - server.post('/ghost/api/v3/admin/images/', function () { + server.post(`${ghostPaths().apiRoot}/images/`, function () { return [500, {'Content-Type': 'application/json'}, '']; }); await render(hbs`{{gh-file-uploader url=uploadUrl}}`); diff --git a/tests/integration/components/gh-image-uploader-test.js b/tests/integration/components/gh-image-uploader-test.js index bb9e77fe6..8b2d5b223 100644 --- a/tests/integration/components/gh-image-uploader-test.js +++ b/tests/integration/components/gh-image-uploader-test.js @@ -1,6 +1,7 @@ import $ from 'jquery'; import Pretender from 'pretender'; import Service from '@ember/service'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import hbs from 'htmlbars-inline-precompile'; import sinon from 'sinon'; import {UnsupportedMediaTypeError} from 'ghost-admin/services/ajax'; @@ -29,13 +30,13 @@ const sessionStub = Service.extend({ }); const stubSuccessfulUpload = function (server, delay = 0) { - server.post('/ghost/api/v3/admin/images/upload/', function () { + server.post(`${ghostPaths().apiRoot}/images/upload/`, function () { return [200, {'Content-Type': 'application/json'}, '{"images": [{"url":"/content/images/test.png"}]}']; }, delay); }; const stubFailedUpload = function (server, code, error, delay = 0) { - server.post('/ghost/api/v3/admin/images/upload/', function () { + server.post(`${ghostPaths().apiRoot}/images/upload/`, function () { return [code, {'Content-Type': 'application/json'}, JSON.stringify({ errors: [{ type: error, @@ -78,7 +79,7 @@ describe('Integration: Component: gh-image-uploader', function () { await fileUpload('input[type="file"]', ['test'], {name: 'test.png'}); expect(server.handledRequests.length).to.equal(1); - expect(server.handledRequests[0].url).to.equal('/ghost/api/v3/admin/images/upload/'); + expect(server.handledRequests[0].url).to.equal(`${ghostPaths().apiRoot}/images/upload/`); expect(server.handledRequests[0].requestHeaders.Authorization).to.be.undefined; }); @@ -177,7 +178,7 @@ describe('Integration: Component: gh-image-uploader', function () { }); it('handles file too large error directly from the web server', async function () { - server.post('/ghost/api/v3/admin/images/upload/', function () { + server.post(`${ghostPaths().apiRoot}/images/upload/`, function () { return [413, {}, '']; }); await render(hbs`{{gh-image-uploader image=image update=(action update)}}`); @@ -197,7 +198,7 @@ describe('Integration: Component: gh-image-uploader', function () { }); it('handles unknown failure', async function () { - server.post('/ghost/api/v3/admin/images/upload/', function () { + server.post(`${ghostPaths().apiRoot}/images/upload/`, function () { return [500, {'Content-Type': 'application/json'}, '']; }); await render(hbs`{{gh-image-uploader image=image update=(action update)}}`); diff --git a/tests/integration/components/gh-uploader-test.js b/tests/integration/components/gh-uploader-test.js index e07e0c3cb..d9f928b26 100644 --- a/tests/integration/components/gh-uploader-test.js +++ b/tests/integration/components/gh-uploader-test.js @@ -1,4 +1,5 @@ import Pretender from 'pretender'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import hbs from 'htmlbars-inline-precompile'; import sinon from 'sinon'; import {click, find, findAll, render, settled, waitFor, waitUntil} from '@ember/test-helpers'; @@ -8,13 +9,13 @@ import {expect} from 'chai'; import {setupRenderingTest} from 'ember-mocha'; const stubSuccessfulUpload = function (server, delay = 0) { - server.post('/ghost/api/v3/admin/images/upload/', function () { + server.post(`${ghostPaths().apiRoot}/images/upload/`, function () { return [200, {'Content-Type': 'application/json'}, '{"images": [{"url": "/content/images/test.png"}]}']; }, delay); }; const stubFailedUpload = function (server, code, error, delay = 0) { - server.post('/ghost/api/v3/admin/images/upload/', function () { + server.post(`${ghostPaths().apiRoot}/images/upload/`, function () { return [code, {'Content-Type': 'application/json'}, JSON.stringify({ errors: [{ type: error, @@ -50,7 +51,7 @@ describe('Integration: Component: gh-uploader', function () { let [lastRequest] = server.handledRequests; expect(server.handledRequests.length).to.equal(1); - expect(lastRequest.url).to.equal('/ghost/api/v3/admin/images/upload/'); + expect(lastRequest.url).to.equal(`${ghostPaths().apiRoot}/images/upload/`); // requestBody is a FormData object // this will fail in anything other than Chrome and Firefox // https://developer.mozilla.org/en-US/docs/Web/API/FormData#Browser_compatibility @@ -135,7 +136,7 @@ describe('Integration: Component: gh-uploader', function () { it('onComplete returns results in same order as selected', async function () { // first request has a delay to simulate larger file - server.post('/ghost/api/v3/admin/images/upload/', function () { + server.post(`${ghostPaths().apiRoot}/images/upload/`, function () { // second request has no delay to simulate small file stubSuccessfulUpload(server, 0); @@ -257,7 +258,7 @@ describe('Integration: Component: gh-uploader', function () { }); it('uploads to supplied `uploadUrl`', async function () { - server.post('/ghost/api/v3/admin/images/', function () { + server.post(`${ghostPaths().apiRoot}/images/`, function () { return [200, {'Content-Type': 'application/json'}, '{"images": [{"url": "/content/images/test.png"}]']; }); @@ -266,7 +267,7 @@ describe('Integration: Component: gh-uploader', function () { await settled(); let [lastRequest] = server.handledRequests; - expect(lastRequest.url).to.equal('/ghost/api/v3/admin/images/'); + expect(lastRequest.url).to.equal(`${ghostPaths().apiRoot}/images/`); }); it('passes supplied paramName in request', async function () { diff --git a/tests/integration/components/modal-import-members-test.js b/tests/integration/components/modal-import-members-test.js index a600738b6..ba429ab2b 100644 --- a/tests/integration/components/modal-import-members-test.js +++ b/tests/integration/components/modal-import-members-test.js @@ -1,5 +1,6 @@ import Pretender from 'pretender'; import Service from '@ember/service'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import hbs from 'htmlbars-inline-precompile'; import sinon from 'sinon'; import {click, find, findAll, render, waitFor} from '@ember/test-helpers'; @@ -15,13 +16,13 @@ const notificationsStub = Service.extend({ }); const stubSuccessfulUpload = function (server, delay = 0) { - server.post('/ghost/api/v3/admin/members/upload/', function () { + server.post(`${ghostPaths().apiRoot}/members/upload/`, function () { return [200, {'Content-Type': 'application/json'}, '{"url":"/content/images/test.png"}']; }, delay); }; const stubFailedUpload = function (server, code, error, delay = 0) { - server.post('/ghost/api/v3/admin/members/upload/', function () { + server.post(`${ghostPaths().apiRoot}/members/upload/`, function () { return [code, {'Content-Type': 'application/json'}, JSON.stringify({ errors: [{ type: error, @@ -38,7 +39,7 @@ describe('Integration: Component: modal-import-members-test', function () { beforeEach(function () { server = new Pretender(); - this.set('uploadUrl', '/ghost/api/v3/admin/members/upload/'); + this.set('uploadUrl', `${ghostPaths().apiRoot}/members/upload/`); this.owner.register('service:notifications', notificationsStub); }); @@ -71,7 +72,7 @@ describe('Integration: Component: modal-import-members-test', function () { await click('.gh-btn-green'); expect(server.handledRequests.length).to.equal(1); - expect(server.handledRequests[0].url).to.equal('/ghost/api/v3/admin/members/upload/'); + expect(server.handledRequests[0].url).to.equal(`${ghostPaths().apiRoot}/members/upload/`); }); it('displays server error', async function () { @@ -101,7 +102,7 @@ describe('Integration: Component: modal-import-members-test', function () { }); it('handles file too large error directly from the web server', async function () { - server.post('/ghost/api/v3/admin/members/upload/', function () { + server.post(`${ghostPaths().apiRoot}/members/upload/`, function () { return [413, {}, '']; }); await render(hbs`{{modal-import-members}}`); @@ -129,7 +130,7 @@ describe('Integration: Component: modal-import-members-test', function () { }); it('handles unknown failure', async function () { - server.post('/ghost/api/v3/admin/members/upload/', function () { + server.post(`${ghostPaths().apiRoot}/members/upload/`, function () { return [500, {'Content-Type': 'application/json'}, '']; }); await render(hbs`{{modal-import-members}}`); diff --git a/tests/integration/services/config-test.js b/tests/integration/services/config-test.js index 7b02a1e28..11f6c29b4 100644 --- a/tests/integration/services/config-test.js +++ b/tests/integration/services/config-test.js @@ -1,4 +1,5 @@ import Pretender from 'pretender'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import wait from 'ember-test-helpers/wait'; import {describe, it} from 'mocha'; import {expect} from 'chai'; @@ -32,7 +33,7 @@ describe('Integration: Service: config', function () { it('normalizes blogUrl to non-trailing-slash', function (done) { let stubBlogUrl = function stubBlogUrl(url) { - server.get('/ghost/api/v3/admin/config/', function () { + server.get(`${ghostPaths().apiRoot}/config/`, function () { return [ 200, {'Content-Type': 'application/json'}, @@ -40,7 +41,7 @@ describe('Integration: Service: config', function () { ]; }); - server.get('/ghost/api/v3/admin/site/', function () { + server.get(`${ghostPaths().apiRoot}/site/`, function () { return [ 200, {'Content-Type': 'application/json'}, diff --git a/tests/integration/services/feature-test.js b/tests/integration/services/feature-test.js index 064a258e2..ece333534 100644 --- a/tests/integration/services/feature-test.js +++ b/tests/integration/services/feature-test.js @@ -1,6 +1,7 @@ import EmberError from '@ember/error'; import FeatureService, {feature} from 'ghost-admin/services/feature'; import Pretender from 'pretender'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import wait from 'ember-test-helpers/wait'; import {describe, it} from 'mocha'; import {expect} from 'chai'; @@ -17,11 +18,11 @@ function stubSettings(server, labs, validSave = true) { } ]; - server.get('/ghost/api/v3/admin/settings/', function () { + server.get(`${ghostPaths().apiRoot}/settings/`, function () { return [200, {'Content-Type': 'application/json'}, JSON.stringify({settings})]; }); - server.put('/ghost/api/v3/admin/settings/', function (request) { + server.put(`${ghostPaths().apiRoot}/settings/`, function (request) { let statusCode = (validSave) ? 200 : 400; let response = (validSave) ? request.requestBody : JSON.stringify({ errors: [{ @@ -47,11 +48,11 @@ function stubUser(server, accessibility, validSave = true) { }] }]; - server.get('/ghost/api/v3/admin/users/me/', function () { + server.get(`${ghostPaths().apiRoot}/users/me/`, function () { return [200, {'Content-Type': 'application/json'}, JSON.stringify({users})]; }); - server.put('/ghost/api/v3/admin/users/1/', function (request) { + server.put(`${ghostPaths().apiRoot}/users/1/`, function (request) { let statusCode = (validSave) ? 200 : 400; let response = (validSave) ? request.requestBody : JSON.stringify({ errors: [{ diff --git a/tests/integration/services/slug-generator-test.js b/tests/integration/services/slug-generator-test.js index 80c980471..29bbc8c86 100644 --- a/tests/integration/services/slug-generator-test.js +++ b/tests/integration/services/slug-generator-test.js @@ -1,11 +1,12 @@ import Pretender from 'pretender'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import {dasherize} from '@ember/string'; import {describe, it} from 'mocha'; import {expect} from 'chai'; import {setupTest} from 'ember-mocha'; function stubSlugEndpoint(server, type, slug) { - server.get('/ghost/api/v3/admin/slugs/:type/:slug/', function (request) { + server.get(`${ghostPaths().apiRoot}/slugs/:type/:slug/`, function (request) { expect(request.params.type).to.equal(type); expect(request.params.slug).to.equal(slug); diff --git a/tests/integration/services/store-test.js b/tests/integration/services/store-test.js index e7d5a5f49..abbb69ac1 100644 --- a/tests/integration/services/store-test.js +++ b/tests/integration/services/store-test.js @@ -1,5 +1,6 @@ import Pretender from 'pretender'; import config from 'ghost-admin/config/environment'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import {describe, it} from 'mocha'; import {expect} from 'chai'; import {setupTest} from 'ember-mocha'; @@ -21,7 +22,7 @@ describe('Integration: Service: store', function () { let {version} = config.APP; let store = this.owner.lookup('service:store'); - server.get('/ghost/api/v3/admin/posts/1/', function () { + server.get(`${ghostPaths().apiRoot}/posts/1/`, function () { return [ 404, {'Content-Type': 'application/json'}, diff --git a/tests/unit/authenticators/cookie-test.js b/tests/unit/authenticators/cookie-test.js index 6a88a389e..68c2c8bb4 100644 --- a/tests/unit/authenticators/cookie-test.js +++ b/tests/unit/authenticators/cookie-test.js @@ -1,4 +1,5 @@ import Service from '@ember/service'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import sinon from 'sinon'; import {beforeEach, describe, it} from 'mocha'; import {expect} from 'chai'; @@ -42,7 +43,7 @@ const mockTour = Service.extend({ }); const mockGhostPaths = Service.extend({ - apiRoot: '/ghost/api/v3/admin' + apiRoot: ghostPaths().apiRoot }); describe('Unit: Authenticator: cookie', () => { @@ -74,7 +75,7 @@ describe('Unit: Authenticator: cookie', () => { let tour = this.owner.lookup('service:tour'); return authenticator.authenticate('AzureDiamond', 'hunter2').then(() => { - expect(post.args[0][0]).to.equal('/ghost/api/v3/admin/session'); + expect(post.args[0][0]).to.equal(`${ghostPaths().apiRoot}/session`); expect(post.args[0][1]).to.deep.include({ data: { username: 'AzureDiamond', @@ -103,7 +104,7 @@ describe('Unit: Authenticator: cookie', () => { let del = authenticator.ajax.del; return authenticator.invalidate().then(() => { - expect(del.args[0][0]).to.equal('/ghost/api/v3/admin/session'); + expect(del.args[0][0]).to.equal(`${ghostPaths().apiRoot}/session`); }); }); }); diff --git a/tests/unit/models/invite-test.js b/tests/unit/models/invite-test.js index 23002ccf9..d4770a983 100644 --- a/tests/unit/models/invite-test.js +++ b/tests/unit/models/invite-test.js @@ -1,4 +1,5 @@ import Pretender from 'pretender'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import {describe, it} from 'mocha'; import {expect} from 'chai'; import {run} from '@ember/runloop'; @@ -23,7 +24,7 @@ describe('Unit: Model: invite', function () { let model = store.createRecord('invite'); let role; - server.post('/ghost/api/v3/admin/invites/', function () { + server.post(`${ghostPaths().apiRoot}/invites/`, function () { return [200, {}, '{}']; }); diff --git a/tests/unit/serializers/notification-test.js b/tests/unit/serializers/notification-test.js index 4f4fc9d5c..47ebd3c56 100644 --- a/tests/unit/serializers/notification-test.js +++ b/tests/unit/serializers/notification-test.js @@ -1,4 +1,5 @@ import Pretender from 'pretender'; +import ghostPaths from 'ghost-admin/utils/ghost-paths'; import {describe, it} from 'mocha'; import {expect} from 'chai'; import {setupTest} from 'ember-mocha'; @@ -17,7 +18,7 @@ describe('Unit: Serializer: notification', function () { }); it('converts location->key when deserializing', function () { - server.get('/ghost/api/v3/admin/notifications', function () { + server.get(`${ghostPaths().apiRoot}/notifications`, function () { let response = { notifications: [{ id: 1,