Skip to content

Commit d260eef

Browse files
authored
fix: STRF-13605 Support local to be channel-specific (#1318)
1 parent 45753bf commit d260eef

File tree

3 files changed

+77
-18
lines changed

3 files changed

+77
-18
lines changed

lib/stencil-start.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,35 +58,38 @@ class StencilStart {
5858
const initialStencilConfig = await this._stencilConfigManager.read();
5959
// Use initial (before updates) port for BrowserSync
6060
const browserSyncPort = cliOptions.port || initialStencilConfig.port;
61-
const channelUrl = await this.getChannelUrl(initialStencilConfig, cliOptions);
61+
const channelInfo = await this.getChannelInfo(initialStencilConfig, cliOptions);
6262
const storeInfoFromAPI = await this._themeApiClient.checkCliVersion({
63-
storeUrl: channelUrl,
63+
storeUrl: channelInfo.url,
6464
});
6565
const updatedStencilConfig = this.updateStencilConfig(
6666
initialStencilConfig,
6767
storeInfoFromAPI,
6868
browserSyncPort,
6969
);
70+
7071
this._storeSettingsLocale = await this.getStoreSettingsLocale(
7172
cliOptions,
7273
updatedStencilConfig,
74+
channelInfo.channel_id,
7375
);
7476
await this.startLocalServer(cliOptions, updatedStencilConfig);
7577
this._logger.log(this.getStartUpInfo(updatedStencilConfig));
7678
await this.startBrowserSync(cliOptions, browserSyncPort);
7779
}
7880

79-
async getStoreSettingsLocale(cliOptions, stencilConfig) {
81+
async getStoreSettingsLocale(cliOptions, stencilConfig, channelId) {
8082
const { accessToken } = stencilConfig;
8183
const apiHost = cliOptions.apiHost || stencilConfig.apiHost;
8284
return this._storeSettingsApiClient.getStoreSettingsLocale({
8385
storeHash: this.storeHash,
8486
accessToken,
8587
apiHost,
88+
channelId,
8689
});
8790
}
8891

89-
async getChannelUrl(stencilConfig, cliOptions) {
92+
async getChannelInfo(stencilConfig, cliOptions) {
9093
const { accessToken } = stencilConfig;
9194
const apiHost = cliOptions.apiHost || stencilConfig.apiHost;
9295
this.storeHash = await this._themeApiClient.getStoreHash({
@@ -106,7 +109,7 @@ class StencilStart {
106109
const foundChannel = channels.find(
107110
(channel) => channel.channel_id === parseInt(channelId, 10),
108111
);
109-
return foundChannel ? foundChannel.url : null;
112+
return foundChannel || null;
110113
}
111114

112115
/**

lib/stencil-start.spec.js

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,22 +137,27 @@ describe('StencilStart unit tests', () => {
137137
const storeHash = 'storeHash_value';
138138
const channelId = 5;
139139
const storeUrl = 'https://www.example.com';
140-
it('should obtain channel id from the api', async () => {
140+
it('should obtain channel info object from the api when no channelUrl is provided', async () => {
141141
const channels = [{ channel_id: channelId, url: storeUrl }];
142142
const themeApiClientStub = {
143143
checkCliVersion: jest.fn(),
144144
getStoreHash: jest.fn().mockResolvedValue(storeHash),
145145
getStoreChannels: jest.fn().mockResolvedValue(channels),
146146
};
147+
const stencilPushUtilsStub = {
148+
promptUserToSelectChannel: jest.fn().mockResolvedValue(channelId),
149+
};
147150
const { instance } = createStencilStartInstance({
148151
themeApiClient: themeApiClientStub,
149-
stencilPushUtils: stencilPushUtilsModule,
152+
stencilPushUtils: stencilPushUtilsStub,
150153
});
151-
const result = await instance.getChannelUrl({ accessToken }, { apiHost });
152-
expect(result).toEqual(storeUrl);
154+
const stencilConfig = { accessToken, normalStoreUrl: 'https://example.com', apiHost };
155+
const cliOptions = { apiHost };
156+
const result = await instance.getChannelInfo(stencilConfig, cliOptions);
157+
expect(result).toEqual(channels[0]);
153158
});
154159

155-
it('should obtain channel url from the CLI', async () => {
160+
it('should return the channelUrl string from cliOptions if provided', async () => {
156161
const channelUrl = 'https://shop.bigcommerce.com';
157162
const channels = [{ channel_id: channelId, url: storeUrl }];
158163
const themeApiClientStub = {
@@ -164,7 +169,9 @@ describe('StencilStart unit tests', () => {
164169
themeApiClient: themeApiClientStub,
165170
stencilPushUtils: stencilPushUtilsModule,
166171
});
167-
const result = await instance.getChannelUrl({ accessToken }, { apiHost, channelUrl });
172+
const stencilConfig = { accessToken, normalStoreUrl: 'https://example.com', apiHost };
173+
const cliOptions = { apiHost, channelUrl };
174+
const result = await instance.getChannelInfo(stencilConfig, cliOptions);
168175
expect(result).toEqual(channelUrl);
169176
});
170177
});
@@ -173,9 +180,23 @@ describe('StencilStart unit tests', () => {
173180
it('should read port from the config file', async () => {
174181
const port = 1234;
175182
const browserSyncStub = getBrowserSyncStub();
183+
const themeApiClientStub = {
184+
checkCliVersion: jest
185+
.fn()
186+
.mockResolvedValue({ baseUrl: 'example.com', sslUrl: 'https://example.com' }),
187+
getStoreHash: jest.fn().mockResolvedValue('storeHash_value'),
188+
getStoreChannels: jest
189+
.fn()
190+
.mockResolvedValue([{ channel_id: 5, url: 'https://www.example.com' }]),
191+
};
192+
const stencilPushUtilsStub = {
193+
promptUserToSelectChannel: jest.fn().mockResolvedValue(5),
194+
};
176195
const { instance } = createStencilStartInstance({
177196
browserSync: browserSyncStub,
178197
stencilConfigManager: getStencilConfigManagerStub({ port }),
198+
themeApiClient: themeApiClientStub,
199+
stencilPushUtils: stencilPushUtilsStub,
179200
});
180201
instance.startLocalServer = jest.fn();
181202
instance.getStartUpInfo = jest.fn().mockReturnValue('Start up info');
@@ -191,9 +212,23 @@ describe('StencilStart unit tests', () => {
191212
it('should read port from the cli', async () => {
192213
const port = 1234;
193214
const browserSyncStub = getBrowserSyncStub();
215+
const themeApiClientStub = {
216+
checkCliVersion: jest
217+
.fn()
218+
.mockResolvedValue({ baseUrl: 'example.com', sslUrl: 'https://example.com' }),
219+
getStoreHash: jest.fn().mockResolvedValue('storeHash_value'),
220+
getStoreChannels: jest
221+
.fn()
222+
.mockResolvedValue([{ channel_id: 5, url: 'https://www.example.com' }]),
223+
};
224+
const stencilPushUtilsStub = {
225+
promptUserToSelectChannel: jest.fn().mockResolvedValue(5),
226+
};
194227
const { instance } = createStencilStartInstance({
195228
browserSync: browserSyncStub,
196229
stencilConfigManager: getStencilConfigManagerStub({ port: 5678 }),
230+
themeApiClient: themeApiClientStub,
231+
stencilPushUtils: stencilPushUtilsStub,
197232
});
198233
instance.startLocalServer = jest.fn();
199234
instance.getStartUpInfo = jest.fn().mockReturnValue('Start up info');

lib/store-settings-api-client.js

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,50 @@ import 'colors';
22
import NetworkUtils from './utils/NetworkUtils.js';
33

44
const networkUtils = new NetworkUtils();
5-
async function getStoreSettingsLocale({ apiHost, storeHash, accessToken }) {
5+
6+
async function getStoreSettingsLocaleWithChannel({ apiHost, storeHash, accessToken, channelId }) {
7+
let url = `${apiHost}/stores/${storeHash}/v3/settings/store/locale`;
8+
if (channelId) {
9+
url += `?channel_id=${channelId}`;
10+
}
11+
const response = await networkUtils.sendApiRequest({
12+
url,
13+
accessToken,
14+
});
15+
16+
return response.data.data;
17+
}
18+
19+
async function getStoreSettingsLocale({ apiHost, storeHash, accessToken, channelId }) {
620
try {
7-
const response = await networkUtils.sendApiRequest({
8-
url: `${apiHost}/stores/${storeHash}/v3/settings/store/locale`,
21+
let data = await getStoreSettingsLocaleWithChannel({
22+
apiHost,
23+
storeHash,
924
accessToken,
25+
channelId,
1026
});
11-
if (!response.data.data) {
27+
// if no data available for the channel provided, default to global setting.
28+
if (!data) {
29+
data = await getStoreSettingsLocaleWithChannel({ apiHost, storeHash, accessToken });
30+
}
31+
if (!data) {
1232
throw new Error('Received empty store locale in the server response'.red);
13-
} else if (!response.data.data.default_shopper_language) {
33+
} else if (!data.default_shopper_language) {
1434
throw new Error(
1535
'Received empty default_shopper_language field in the server response'.red,
1636
);
17-
} else if (!response.data.data.shopper_language_selection_method) {
37+
} else if (!data.shopper_language_selection_method) {
1838
throw new Error(
1939
'Received empty shopper_language_selection_method field in the server response'.red,
2040
);
2141
}
22-
return response.data.data;
42+
return data;
2343
} catch (err) {
2444
err.name = 'StoreSettingsLocaleError';
2545
throw err;
2646
}
2747
}
48+
2849
export { getStoreSettingsLocale };
2950
export default {
3051
getStoreSettingsLocale,

0 commit comments

Comments
 (0)