-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1701 from Shopify/remove-rest-from-remix-future-flag
[Feature] Remove rest using a future flag
- Loading branch information
Showing
60 changed files
with
816 additions
and
528 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
'@shopify/shopify-app-remix': minor | ||
--- | ||
|
||
Added `removeRest` future flag. | ||
|
||
When `removeRest` is `true`, the REST API will no longer be available. Please use the GraphQL API instead. See [Shopify is all-in on graphql](https://www.shopify.com/ca/partners/blog/all-in-on-graphql) for more information. | ||
|
||
If your app doesn't use the REST API, you can safely set `removeRest` to `true` and be ready for a future major release. If your app does use the REST API, you should migrate to the GraphQL API and then set `removeRest` to `true`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,6 @@ database.sqlite | |
packages/**/build | ||
packages/**/*.tgz | ||
tmp/ | ||
.vscode/ | ||
bundle/ | ||
.turbo | ||
.rollup.cache | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"typescript.preferences.importModuleSpecifier": "relative", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
194 changes: 106 additions & 88 deletions
194
packages/apps/shopify-app-remix/src/server/__test-helpers/expect-admin-api-client.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,122 +1,140 @@ | ||
import {Session} from '@shopify/shopify-api'; | ||
|
||
import {LATEST_API_VERSION} from '..'; | ||
import type {AdminApiContext} from '../clients'; | ||
import type { | ||
AdminApiContextWithoutRest, | ||
AdminApiContextWithRest, | ||
} from '../clients'; | ||
|
||
import {mockExternalRequest} from './request-mock'; | ||
import {TEST_SHOP} from './const'; | ||
import {mockExternalRequest} from './request-mock'; | ||
|
||
const REQUEST_URL = `https://${TEST_SHOP}/admin/api/${LATEST_API_VERSION}/customers.json`; | ||
|
||
export function expectAdminApiClient( | ||
factory: () => Promise<{ | ||
admin: AdminApiContext; | ||
admin: AdminApiContextWithRest; | ||
adminWithoutRest?: AdminApiContextWithoutRest; | ||
expectedSession: Session; | ||
actualSession: Session; | ||
}>, | ||
) { | ||
it('REST client can perform GET requests', async () => { | ||
// GIVEN | ||
const {admin} = await factory(); | ||
await mockExternalRequest({ | ||
request: new Request(REQUEST_URL), | ||
response: new Response(JSON.stringify({customers: []})), | ||
describe('when future.removeRest is falsey there is a REST client', () => { | ||
it('can perform GET requests', async () => { | ||
// GIVEN | ||
const {admin} = await factory(); | ||
await mockExternalRequest({ | ||
request: new Request(REQUEST_URL), | ||
response: new Response(JSON.stringify({customers: []})), | ||
}); | ||
|
||
// WHEN | ||
const response = await admin.rest.get({path: 'customers'}); | ||
|
||
// THEN | ||
expect(response.status).toEqual(200); | ||
expect(await response.json()).toEqual({customers: []}); | ||
}); | ||
|
||
// WHEN | ||
const response = await admin.rest.get({path: 'customers'}); | ||
|
||
// THEN | ||
expect(response.status).toEqual(200); | ||
expect(await response.json()).toEqual({customers: []}); | ||
}); | ||
|
||
it('REST client can perform POST requests', async () => { | ||
// GIVEN | ||
const {admin} = await factory(); | ||
await mockExternalRequest({ | ||
request: new Request(REQUEST_URL, {method: 'POST'}), | ||
response: new Response(JSON.stringify({customers: []})), | ||
it('can perform POST requests', async () => { | ||
// GIVEN | ||
const {admin} = await factory(); | ||
await mockExternalRequest({ | ||
request: new Request(REQUEST_URL, {method: 'POST'}), | ||
response: new Response(JSON.stringify({customers: []})), | ||
}); | ||
|
||
// WHEN | ||
const response = await admin.rest.post({ | ||
path: '/customers.json', | ||
data: '', | ||
}); | ||
|
||
// THEN | ||
expect(response.status).toEqual(200); | ||
expect(await response.json()).toEqual({customers: []}); | ||
}); | ||
|
||
// WHEN | ||
const response = await admin.rest.post({ | ||
path: '/customers.json', | ||
data: '', | ||
it('can perform PUT requests', async () => { | ||
// GIVEN | ||
const {admin} = await factory(); | ||
await mockExternalRequest({ | ||
request: new Request(REQUEST_URL, {method: 'PUT'}), | ||
response: new Response(JSON.stringify({customers: []})), | ||
}); | ||
|
||
// WHEN | ||
const response = await admin.rest.put({ | ||
path: '/customers.json', | ||
data: '', | ||
}); | ||
|
||
// THEN | ||
expect(response.status).toEqual(200); | ||
expect(await response.json()).toEqual({customers: []}); | ||
}); | ||
|
||
// THEN | ||
expect(response.status).toEqual(200); | ||
expect(await response.json()).toEqual({customers: []}); | ||
}); | ||
it('can perform DELETE requests', async () => { | ||
// GIVEN | ||
const {admin} = await factory(); | ||
await mockExternalRequest({ | ||
request: new Request(REQUEST_URL, {method: 'DELETE'}), | ||
response: new Response(JSON.stringify({customers: []})), | ||
}); | ||
|
||
it('REST client can perform PUT requests', async () => { | ||
// GIVEN | ||
const {admin} = await factory(); | ||
await mockExternalRequest({ | ||
request: new Request(REQUEST_URL, {method: 'PUT'}), | ||
response: new Response(JSON.stringify({customers: []})), | ||
}); | ||
// WHEN | ||
const response = await admin.rest.delete({path: '/customers.json'}); | ||
|
||
// WHEN | ||
const response = await admin.rest.put({ | ||
path: '/customers.json', | ||
data: '', | ||
// THEN | ||
expect(response.status).toEqual(200); | ||
expect(await response.json()).toEqual({customers: []}); | ||
}); | ||
|
||
// THEN | ||
expect(response.status).toEqual(200); | ||
expect(await response.json()).toEqual({customers: []}); | ||
}); | ||
|
||
it('REST client can perform DELETE requests', async () => { | ||
// GIVEN | ||
const {admin} = await factory(); | ||
await mockExternalRequest({ | ||
request: new Request(REQUEST_URL, {method: 'DELETE'}), | ||
response: new Response(JSON.stringify({customers: []})), | ||
}); | ||
|
||
// WHEN | ||
const response = await admin.rest.delete({path: '/customers.json'}); | ||
describe('when future.removeRest is truthy', () => { | ||
it('does not include a rest property on the admin object', async () => { | ||
// GIVEN | ||
const {adminWithoutRest} = await factory(); | ||
|
||
// THEN | ||
expect(response.status).toEqual(200); | ||
expect(await response.json()).toEqual({customers: []}); | ||
// THEN | ||
expect(adminWithoutRest).not.toHaveProperty('rest'); | ||
}); | ||
}); | ||
|
||
it('GraphQL client can perform requests', async () => { | ||
// GIVEN | ||
const {admin, actualSession} = await factory(); | ||
await mockExternalRequest({ | ||
request: new Request( | ||
`https://${TEST_SHOP}/admin/api/${LATEST_API_VERSION}/graphql.json`, | ||
{ | ||
method: 'POST', | ||
headers: {'X-Shopify-Access-Token': actualSession.accessToken!}, | ||
}, | ||
), | ||
response: new Response( | ||
JSON.stringify({data: {shop: {name: 'Test shop'}}}), | ||
), | ||
describe('Graphql client', () => { | ||
it('can perform requests', async () => { | ||
// GIVEN | ||
const {admin, actualSession} = await factory(); | ||
await mockExternalRequest({ | ||
request: new Request( | ||
`https://${TEST_SHOP}/admin/api/${LATEST_API_VERSION}/graphql.json`, | ||
{ | ||
method: 'POST', | ||
headers: {'X-Shopify-Access-Token': actualSession.accessToken!}, | ||
}, | ||
), | ||
response: new Response( | ||
JSON.stringify({data: {shop: {name: 'Test shop'}}}), | ||
), | ||
}); | ||
|
||
// WHEN | ||
const response = await admin.graphql('{ shop { name } }'); | ||
|
||
// THEN | ||
expect(response.status).toEqual(200); | ||
expect(await response.json()).toEqual({ | ||
data: {shop: {name: 'Test shop'}}, | ||
headers: {'Content-Type': ['application/json']}, | ||
}); | ||
}); | ||
|
||
// WHEN | ||
const response = await admin.graphql('{ shop { name } }'); | ||
it('returns a session object as part of the context', async () => { | ||
// GIVEN | ||
const {expectedSession, actualSession} = await factory(); | ||
|
||
// THEN | ||
expect(response.status).toEqual(200); | ||
expect(await response.json()).toEqual({ | ||
data: {shop: {name: 'Test shop'}}, | ||
headers: {'Content-Type': ['application/json']}, | ||
// THEN | ||
expect(expectedSession).toEqual(actualSession); | ||
}); | ||
}); | ||
|
||
it('returns a session object as part of the context', async () => { | ||
// GIVEN | ||
const {expectedSession, actualSession} = await factory(); | ||
|
||
// THEN | ||
expect(expectedSession).toEqual(actualSession); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.