Skip to content

Commit

Permalink
Merge pull request #527 from Shopify/zoey/redirect-to-install
Browse files Browse the repository at this point in the history
Remix: Redirect to admin install path if future flag is enabled
  • Loading branch information
rachel-carvalho committed Dec 12, 2023
2 parents 470890b + c09d26e commit 92968c8
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const API_KEY = 'testApiKey';
export const APP_URL = 'https://my-test-app.myshopify.io';
export const SHOPIFY_HOST = 'totally-real-host.myshopify.io';
export const BASE64_HOST = Buffer.from(SHOPIFY_HOST).toString('base64');
export const TEST_SHOP = 'test-shop.myshopify.com';
export const TEST_SHOP_NAME = 'test-shop';
export const TEST_SHOP = `${TEST_SHOP_NAME}.myshopify.com`;
export const GRAPHQL_URL = `https://${TEST_SHOP}/admin/api/${LATEST_API_VERSION}/graphql.json`;
export const USER_ID = 12345;
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {LoginErrorType, shopifyApp} from '../../../index';
import {
APP_URL,
TEST_SHOP,
TEST_SHOP_NAME,
getThrownResponse,
testConfig,
} from '../../../__test-helpers';
Expand Down Expand Up @@ -79,25 +80,63 @@ describe('login helper', () => {
},
);

it.each([
{urlShop: null, formShop: TEST_SHOP, method: 'POST'},
{urlShop: TEST_SHOP, formShop: null, method: 'GET'},
{urlShop: null, formShop: 'test-shop', method: 'POST'},
{urlShop: 'test-shop', formShop: null, method: 'GET'},
{urlShop: null, formShop: 'test-shop.myshopify.com', method: 'POST'},
{urlShop: 'test-shop.myshopify.com', formShop: null, method: 'GET'},
])(
'returns a redirect to /auth if the shop is valid: %s',
async ({urlShop, formShop, method}) => {
describe.each([
{isEmbeddedApp: false, futureFlag: false, redirectToInstall: false},
{isEmbeddedApp: true, futureFlag: false, redirectToInstall: false},
{isEmbeddedApp: false, futureFlag: true, redirectToInstall: false},
{isEmbeddedApp: true, futureFlag: true, redirectToInstall: true},
])('Given setup: %s', (testCaseConfig) => {
it.each([
{urlShop: null, formShop: TEST_SHOP, method: 'POST'},
{urlShop: TEST_SHOP, formShop: null, method: 'GET'},
{urlShop: null, formShop: 'test-shop', method: 'POST'},
{urlShop: 'test-shop', formShop: null, method: 'GET'},
{urlShop: null, formShop: 'test-shop.myshopify.com', method: 'POST'},
{urlShop: 'test-shop.myshopify.com', formShop: null, method: 'GET'},
])(
'returns a redirect to auth or install if the shop is valid: %s',
async ({urlShop, formShop, method}) => {
// GIVEN
const config = testConfig({
future: {unstable_newEmbeddedAuthStrategy: testCaseConfig.futureFlag},
isEmbeddedApp: testCaseConfig.isEmbeddedApp,
});
const shopify = shopifyApp(config);
const requestMock = {
url: urlShop
? `${APP_URL}/auth/login?shop=${urlShop}`
: `${APP_URL}/auth/login`,
formData: async () => ({get: () => formShop}),
method,
};

// WHEN
const response = await getThrownResponse(
shopify.login,
requestMock as any as Request,
);

// THEN
const expectedPath = testCaseConfig.redirectToInstall
? `https://admin.shopify.com/store/${TEST_SHOP_NAME}/oauth/install?client_id=${config.apiKey}`
: `${APP_URL}/auth?shop=${TEST_SHOP}`;

expect(response.status).toEqual(302);
expect(response.headers.get('location')).toEqual(expectedPath);
},
);

it('sanitizes the shop parameter', async () => {
// GIVEN
const config = testConfig();
const shopify = shopifyApp(testConfig());
const config = testConfig({
future: {unstable_newEmbeddedAuthStrategy: testCaseConfig.futureFlag},
isEmbeddedApp: testCaseConfig.isEmbeddedApp,
});
const shopify = shopifyApp(config);
const requestMock = {
url: urlShop
? `${APP_URL}/auth/login?shop=${urlShop}`
: `${APP_URL}/auth/login`,
formData: async () => ({get: () => formShop}),
method,
url: `${APP_URL}/auth/login`,
formData: async () => ({get: () => `https://${TEST_SHOP}/`}),
method: 'POST',
};

// WHEN
Expand All @@ -106,33 +145,13 @@ describe('login helper', () => {
requestMock as any as Request,
);

const expectedPath = testCaseConfig.redirectToInstall
? `https://admin.shopify.com/store/${TEST_SHOP_NAME}/oauth/install?client_id=${config.apiKey}`
: `${APP_URL}/auth?shop=${TEST_SHOP}`;

// THEN
expect(response.status).toEqual(302);
expect(response.headers.get('location')).toEqual(
`${APP_URL}/auth?shop=${TEST_SHOP}`,
);
},
);

it('sanitizes the shop parameter', async () => {
// GIVEN
const shopify = shopifyApp(testConfig());
const requestMock = {
url: `${APP_URL}/auth/login`,
formData: async () => ({get: () => `https://${TEST_SHOP}/`}),
method: 'POST',
};

// WHEN
const response = await getThrownResponse(
shopify.login,
requestMock as any as Request,
);

// THEN
expect(response.status).toEqual(302);
expect(response.headers.get('location')).toEqual(
`${APP_URL}/auth?shop=${TEST_SHOP}`,
);
expect(response.headers.get('location')).toEqual(expectedPath);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ export function loginFactory(params: BasicParams) {
return {shop: LoginErrorType.InvalidShop};
}

const redirectUrl = `${config.appUrl}${config.auth.path}?shop=${sanitizedShop}`;
const authPath = `${config.appUrl}${config.auth.path}?shop=${sanitizedShop}`;

const storeName = sanitizedShop.split('.')[0];
const installPath = `https://admin.shopify.com/store/${storeName}/oauth/install?client_id=${config.apiKey}`;

const shouldInstall =
config.isEmbeddedApp && config.future.unstable_newEmbeddedAuthStrategy;
const redirectUrl = shouldInstall ? installPath : authPath;

logger.info(`Redirecting login request to ${redirectUrl}`, {
shop: sanitizedShop,
Expand Down

0 comments on commit 92968c8

Please sign in to comment.