Skip to content

Commit 60fe291

Browse files
committed
update tests for future flag
1 parent 78173f0 commit 60fe291

File tree

7 files changed

+256
-159
lines changed

7 files changed

+256
-159
lines changed

Diff for: packages/apps/shopify-app-remix/src/server/__test-helpers/setup-embedded-flow.ts

+28
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,31 @@ export async function setUpEmbeddedFlowWithRemoveRestFlag() {
6161
request,
6262
};
6363
}
64+
65+
export async function setUpEmbeddedFlowWithSingleFetch() {
66+
const shopify = shopifyApp({
67+
...testConfig({
68+
restResources,
69+
}),
70+
future: {
71+
removeRest: false,
72+
unstable_newEmbeddedAuthStrategy: false,
73+
remixSingleFetch: true,
74+
},
75+
});
76+
const expectedSession = await setUpValidSession(shopify.sessionStorage);
77+
78+
const {token} = getJwt();
79+
const request = new Request(
80+
`${APP_URL}?embedded=1&shop=${TEST_SHOP}&host=${BASE64_HOST}&id_token=${token}`,
81+
);
82+
83+
const result = await shopify.authenticate.admin(request);
84+
85+
return {
86+
shopify,
87+
expectedSession,
88+
...result,
89+
request,
90+
};
91+
}

Diff for: packages/apps/shopify-app-remix/src/server/__test-helpers/setup-fetch-flow.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {testConfig} from './test-config';
99

1010
export async function setUpFetchFlow(flags?: {
1111
unstable_newEmbeddedAuthStrategy?: boolean;
12+
remixSingleFetch?: boolean;
1213
}) {
1314
const shopify = shopifyApp({
1415
...testConfig({

Diff for: packages/apps/shopify-app-remix/src/server/__test-helpers/setup-non-embedded-flow.ts

+16-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,24 @@ import {setUpValidSession} from './setup-valid-session';
88
import {signRequestCookie} from './sign-request-cookie';
99
import {testConfig} from './test-config';
1010

11-
export async function setUpNonEmbeddedFlow() {
11+
interface NonEmbeddedFlowOptions {
12+
remixSingleFetch?: boolean;
13+
unstable_newEmbeddedAuthStrategy?: boolean;
14+
}
15+
16+
export async function setUpNonEmbeddedFlow(
17+
options: NonEmbeddedFlowOptions = {},
18+
) {
19+
const {remixSingleFetch = false, unstable_newEmbeddedAuthStrategy = false} =
20+
options;
21+
1222
const shopify = shopifyApp({
1323
...testConfig({restResources, isEmbeddedApp: false}),
14-
future: {removeRest: false},
24+
future: {
25+
removeRest: false,
26+
remixSingleFetch,
27+
unstable_newEmbeddedAuthStrategy,
28+
},
1529
});
1630
const session = await setUpValidSession(shopify.sessionStorage);
1731

Diff for: packages/apps/shopify-app-remix/src/server/authenticate/admin/scope/__tests__/query.test.ts

+95-68
Original file line numberDiff line numberDiff line change
@@ -7,94 +7,121 @@ import {
77
setUpEmbeddedFlow,
88
setUpFetchFlow,
99
setUpNonEmbeddedFlow,
10+
setUpEmbeddedFlowWithSingleFetch,
1011
} from '../../../../__test-helpers';
1112
import {REAUTH_URL_HEADER} from '../../../const';
1213

1314
import * as responses from './mock-responses';
1415

15-
it('returns scopes information', async () => {
16-
// GIVEN
17-
const {scopes} = await setUpEmbeddedFlow();
18-
await mockGraphqlRequest()({
19-
status: 200,
20-
responseContent: responses.WITH_GRANTED_AND_DECLARED,
16+
describe.each([
17+
['with standard embedded flow', setUpEmbeddedFlow],
18+
['with single fetch embedded flow', setUpEmbeddedFlowWithSingleFetch],
19+
])('%s', (_, setupFn) => {
20+
it('returns scopes information', async () => {
21+
// GIVEN
22+
const {scopes} = await setupFn();
23+
await mockGraphqlRequest()({
24+
status: 200,
25+
responseContent: responses.WITH_GRANTED_AND_DECLARED,
26+
});
27+
28+
// WHEN
29+
const result = await scopes.query();
30+
// THEN
31+
expect(result).not.toBeUndefined();
32+
expect(result.granted).toEqual([
33+
'read_orders',
34+
'read_reports',
35+
'read_products',
36+
'read_customers',
37+
'write_customers',
38+
]);
39+
expect(result.required).toEqual([
40+
'read_orders',
41+
'read_reports',
42+
'read_products',
43+
]);
44+
expect(result.optional).toEqual(['write_customers', 'write_products']);
2145
});
2246

23-
// WHEN
24-
const result = await scopes.query();
25-
// THEN
26-
expect(result).not.toBeUndefined();
27-
expect(result.granted).toEqual([
28-
'read_orders',
29-
'read_reports',
30-
'read_products',
31-
'read_customers',
32-
'write_customers',
33-
]);
34-
expect(result.required).toEqual([
35-
'read_orders',
36-
'read_reports',
37-
'read_products',
38-
]);
39-
expect(result.optional).toEqual(['write_customers', 'write_products']);
40-
});
47+
it('redirects to exit-iframe with authentication using app bridge when embedded and Shopify invalidated the session', async () => {
48+
// GIVEN
49+
const {scopes} = await setupFn();
50+
const requestMock = await mockGraphqlRequest()({status: 401});
4151

42-
it('redirects to exit-iframe with authentication using app bridge when embedded and Shopify invalidated the session', async () => {
43-
// GIVEN
44-
const {scopes} = await setUpEmbeddedFlow();
45-
const requestMock = await mockGraphqlRequest()({status: 401});
52+
// WHEN
53+
const response = await getThrownResponse(
54+
async () => scopes.query(),
55+
requestMock,
56+
);
4657

47-
// WHEN
48-
const response = await getThrownResponse(
49-
async () => scopes.query(),
50-
requestMock,
51-
);
52-
53-
// THEN
54-
expectExitIframeRedirect(response);
58+
// THEN
59+
expectExitIframeRedirect(response);
60+
});
5561
});
5662

57-
it('returns app bridge redirection during request headers when Shopify invalidated the session', async () => {
58-
// GIVEN
59-
const {scopes} = await setUpFetchFlow({
60-
unstable_newEmbeddedAuthStrategy: false,
63+
describe.each([
64+
['with standard fetch flow', false],
65+
['with single fetch flow', true],
66+
])('%s', (_, remixSingleFetch) => {
67+
it('returns app bridge redirection during request headers when Shopify invalidated the session', async () => {
68+
// GIVEN
69+
const {scopes} = await setUpFetchFlow({
70+
unstable_newEmbeddedAuthStrategy: false,
71+
remixSingleFetch,
72+
});
73+
const requestMock = await mockGraphqlRequest()({status: 401});
74+
75+
// WHEN
76+
const response = await getThrownResponse(
77+
async () => scopes.query(),
78+
requestMock,
79+
);
80+
81+
// THEN
82+
expect(response.status).toEqual(remixSingleFetch ? 302 : 401);
83+
84+
const {origin, pathname, searchParams} = new URL(
85+
response.headers.get(REAUTH_URL_HEADER)!,
86+
);
87+
expect(origin).toEqual(APP_URL);
88+
expect(pathname).toEqual('/auth');
89+
expect(searchParams.get('shop')).toEqual(TEST_SHOP);
6190
});
62-
const requestMock = await mockGraphqlRequest()({status: 401});
6391

64-
// WHEN
65-
const response = await getThrownResponse(
66-
async () => scopes.query(),
67-
requestMock,
68-
);
92+
it('returns a normal redirection when the app is non embedded and Shopify invalidated the session', async () => {
93+
// GIVEN
94+
const {scopes} = await setUpNonEmbeddedFlow();
95+
const requestMock = await mockGraphqlRequest()({status: 401});
6996

70-
// THEN
71-
expect(response.status).toEqual(302);
97+
// WHEN
98+
const response = await getThrownResponse(
99+
async () => scopes.query(),
100+
requestMock,
101+
);
72102

73-
const {origin, pathname, searchParams} = new URL(
74-
response.headers.get(REAUTH_URL_HEADER)!,
75-
);
76-
expect(origin).toEqual(APP_URL);
77-
expect(pathname).toEqual('/auth');
78-
expect(searchParams.get('shop')).toEqual(TEST_SHOP);
103+
// THEN
104+
expect(response.status).toEqual(302);
105+
106+
const {hostname, pathname} = new URL(response.headers.get('Location')!);
107+
expect(hostname).toEqual(TEST_SHOP);
108+
expect(pathname).toEqual('/admin/oauth/authorize');
109+
});
79110
});
80111

81-
it('returns a normal redirection when the app is non embedded and Shopify invalidated the session', async () => {
112+
it('return an unexpected error when there is no authentication error', async () => {
82113
// GIVEN
83-
const {scopes} = await setUpNonEmbeddedFlow();
84-
const requestMock = await mockGraphqlRequest()({status: 401});
114+
const {scopes} = await setUpFetchFlow({
115+
unstable_newEmbeddedAuthStrategy: false,
116+
});
117+
await mockGraphqlRequest()({status: 500});
85118

86-
// WHEN
87-
const response = await getThrownResponse(
88-
async () => scopes.query(),
89-
requestMock,
119+
// WHEN / THEN
120+
await expect(scopes.query()).rejects.toEqual(
121+
expect.objectContaining({
122+
status: 500,
123+
}),
90124
);
91-
92-
// THEN
93-
expect(response.status).toEqual(302);
94-
95-
const {hostname, pathname} = new URL(response.headers.get('Location')!);
96-
expect(hostname).toEqual(TEST_SHOP);
97-
expect(pathname).toEqual('/admin/oauth/authorize');
98125
});
99126

100127
it('return an unexpected error when there is no authentication error', async () => {

Diff for: packages/apps/shopify-app-remix/src/server/authenticate/admin/scope/__tests__/request.test.ts

+33-27
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
TEST_SHOP_NAME,
77
getThrownResponse,
88
setUpEmbeddedFlow,
9+
setUpEmbeddedFlowWithSingleFetch,
910
setUpNonEmbeddedFlow,
1011
setUpValidSession,
1112
signRequestCookie,
@@ -123,33 +124,38 @@ describe('request from a non embedded app', () => {
123124
});
124125

125126
describe('request from an embedded app', () => {
126-
it('redirects to install URL when successful', async () => {
127-
// GIVEN
128-
const {scopes, request} = await setUpEmbeddedFlow();
129-
await mockGraphqlRequest()({
130-
status: 200,
131-
responseContent: responses.WITH_GRANTED_AND_DECLARED,
127+
describe.each([
128+
['with standard embedded flow', setUpEmbeddedFlow, 401],
129+
['with single fetch embedded flow', setUpEmbeddedFlowWithSingleFetch, 302],
130+
])('%s', (_, setupFn, expectedStatus) => {
131+
it('redirects to install URL when successful', async () => {
132+
// GIVEN
133+
const {scopes, request} = await setupFn();
134+
await mockGraphqlRequest()({
135+
status: 200,
136+
responseContent: responses.WITH_GRANTED_AND_DECLARED,
137+
});
138+
139+
// WHEN
140+
const response = await getThrownResponse(
141+
async () =>
142+
scopes.request(['write_products', 'read_orders', 'write_customers']),
143+
request,
144+
);
145+
146+
// THEN
147+
expect(response.status).toEqual(expectedStatus);
148+
const reuthorizeHeader = response.headers.get(
149+
'x-shopify-api-request-failure-reauthorize-url',
150+
);
151+
expect(reuthorizeHeader).not.toBeUndefined();
152+
const location = new URL(reuthorizeHeader!);
153+
expect(location.hostname).toBe(TEST_SHOP);
154+
expect(location.pathname).toBe('/admin/oauth/install');
155+
const locationParams = location.searchParams;
156+
expect(locationParams.get('optional_scopes')).toBe(
157+
'write_products,read_orders,write_customers',
158+
);
132159
});
133-
134-
// WHEN
135-
const response = await getThrownResponse(
136-
async () =>
137-
scopes.request(['write_products', 'read_orders', 'write_customers']),
138-
request,
139-
);
140-
141-
// THEN
142-
expect(response.status).toEqual(302);
143-
const reuthorizeHeader = response.headers.get(
144-
'x-shopify-api-request-failure-reauthorize-url',
145-
);
146-
expect(reuthorizeHeader).not.toBeUndefined();
147-
const location = new URL(reuthorizeHeader!);
148-
expect(location.hostname).toBe(TEST_SHOP);
149-
expect(location.pathname).toBe('/admin/oauth/install');
150-
const locationParams = location.searchParams;
151-
expect(locationParams.get('optional_scopes')).toBe(
152-
'write_products,read_orders,write_customers',
153-
);
154160
});
155161
});

Diff for: packages/apps/shopify-app-remix/src/server/authenticate/admin/scope/__tests__/revoke.test.ts

+30-24
Original file line numberDiff line numberDiff line change
@@ -90,31 +90,37 @@ it('redirects to exit-iframe with authentication using app bridge when embedded
9090
expectExitIframeRedirect(response);
9191
});
9292

93-
it('returns app bridge redirection during request headers when Shopify invalidated the session', async () => {
94-
// GIVEN
95-
const {scopes} = await setUpFetchFlow({
96-
unstable_newEmbeddedAuthStrategy: false,
93+
describe.each([
94+
['with standard fetch flow', false],
95+
['with single fetch flow', true],
96+
])('%s', (_, remixSingleFetch) => {
97+
it('returns app bridge redirection during request headers when Shopify invalidated the session', async () => {
98+
// GIVEN
99+
const {scopes} = await setUpFetchFlow({
100+
unstable_newEmbeddedAuthStrategy: false,
101+
remixSingleFetch,
102+
});
103+
const mockedRequests = await mockGraphqlRequests()({
104+
body: 'AppRevokeAccessScopes',
105+
status: 401,
106+
});
107+
108+
// WHEN
109+
const response = await getThrownResponse(
110+
async () => scopes.revoke(['read_orders']),
111+
mockedRequests[0],
112+
);
113+
114+
// THEN
115+
expect(response.status).toEqual(remixSingleFetch ? 302 : 401);
116+
117+
const {origin, pathname, searchParams} = new URL(
118+
response.headers.get(REAUTH_URL_HEADER)!,
119+
);
120+
expect(origin).toEqual(APP_URL);
121+
expect(pathname).toEqual('/auth');
122+
expect(searchParams.get('shop')).toEqual(TEST_SHOP);
97123
});
98-
const mockedRequests = await mockGraphqlRequests()({
99-
body: 'AppRevokeAccessScopes',
100-
status: 401,
101-
});
102-
103-
// WHEN
104-
const response = await getThrownResponse(
105-
async () => scopes.revoke(['read_orders']),
106-
mockedRequests[0],
107-
);
108-
109-
// THEN
110-
expect(response.status).toEqual(302);
111-
112-
const {origin, pathname, searchParams} = new URL(
113-
response.headers.get(REAUTH_URL_HEADER)!,
114-
);
115-
expect(origin).toEqual(APP_URL);
116-
expect(pathname).toEqual('/auth');
117-
expect(searchParams.get('shop')).toEqual(TEST_SHOP);
118124
});
119125

120126
it('returns a normal redirection when the app is non embedded and Shopify invalidated the session', async () => {

0 commit comments

Comments
 (0)