Skip to content

Commit c8e48c4

Browse files
Merge pull request #1555 from appknox/CJB-478-ui-bug-after-switching-file-ids-from-address-bar-internal
Breadcrumbs UI Bug Fix
2 parents e32fd0a + 44fab9a commit c8e48c4

File tree

4 files changed

+142
-8
lines changed

4 files changed

+142
-8
lines changed

app/components/sso-settings/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ export default class SsoSettingsComponent extends Component<SsoSettingsSignature
149149

150150
await this.ajax.post(url, {
151151
data: idpFormData,
152+
contentType: null,
152153
});
153154

154155
this.idpMetadataXml = null;

app/services/ajax.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ interface RequestOptions extends RequestInit {
1717
/** Optional host URL to override the default API host */
1818
host?: string;
1919
/** Optional Content Type to override the default Content Type */
20-
contentType?: string;
20+
contentType?: string | null;
2121
}
2222

2323
/**
@@ -261,16 +261,15 @@ export default class IreneAjaxService extends Service {
261261
*/
262262
async makeRequest<T>(url: string, options: RequestOptions = {}): Promise<T> {
263263
const finalUrl = this._buildURL(url, options);
264+
const contentType = options.contentType;
264265

265266
// Only include headers if _shouldSendHeaders returns true
266267
const headers = this._shouldSendHeaders(finalUrl, options.host)
267268
? {
268269
// For data transfer objects we allow the browser set the content type of the request
269-
...([FormData, Blob].some(
270-
(dataType) => options.data instanceof dataType
271-
)
270+
...(contentType === null
272271
? {}
273-
: { 'Content-Type': options.contentType || 'application/json' }),
272+
: { 'Content-Type': contentType || 'application/json' }),
274273
...this.defaultHeaders,
275274
...options.headers,
276275
}

app/services/ak-breadcrumbs.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,12 @@ export default class AkBreadcrumbsService extends Service {
300300
return lastTransItems.slice(0, originRouteIndexInCrumbs + 1);
301301
}
302302

303-
return originRouteIsLastCrumbItem ? (lastTransInfo?.items ?? []) : [];
303+
// Necessary to check 'originRouteHasDiffModelWithSameRouteInCrumbs' in scenarios where
304+
// a model change happens on the route which was last added to the crumbs list.
305+
return !originRouteHasDiffModelWithSameRouteInCrumbs &&
306+
originRouteIsLastCrumbItem
307+
? (lastTransInfo?.items ?? [])
308+
: [];
304309
}
305310

306311
/**

tests/acceptance/breadcrumbs-test.js

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const createBCRouteCtrller = (breadcrumbs = {}, empty = false) =>
2626
}
2727
};
2828

29-
// Resgiter a route and its controller and templates
29+
// Register a route and its controller and templates
3030
function setupRoute(
3131
owner,
3232
{ routeName, routeClass, controllerClass, template = null }
@@ -827,7 +827,7 @@ module('Acceptance | Breadcrumbs Test', function (hooks) {
827827
);
828828
});
829829

830-
test('It recalculates breadcrumbs if visiting existing route in crumbs but with different models', async function (assert) {
830+
test('It recalculates breadcrumbs if visiting existing route in crumbs but with different models (Without browser refresh)', async function (assert) {
831831
assert.expect(35);
832832

833833
const parentWithModelRouteFallbackCrumbs = (id) => [
@@ -992,4 +992,133 @@ module('Acceptance | Breadcrumbs Test', function (hooks) {
992992
assert
993993
);
994994
});
995+
996+
test('It recalculates breadcrumbs if visiting existing route in crumbs but with different models (With browser refresh)', async function (assert) {
997+
assert.expect(21);
998+
999+
const parentWithModelRouteFallbackCrumbs = (id) => [
1000+
ALL_ROUTE_CRUMB_PROPS['tr-b-root'],
1001+
{ ...ALL_ROUTE_CRUMB_PROPS['tr-b-root/parent-with-model'], models: [id] },
1002+
];
1003+
1004+
class ParentWithModelController extends Controller {
1005+
get breadcrumbs() {
1006+
return {
1007+
...ALL_ROUTE_CRUMB_PROPS['tr-b-root/parent-with-model'],
1008+
models: [this.model.id],
1009+
fallbackCrumbs: parentWithModelRouteFallbackCrumbs(this.model.id),
1010+
};
1011+
}
1012+
}
1013+
1014+
// Register routes to be tested
1015+
const routesConfig = [
1016+
{
1017+
routeName: 'tr-b-root/index',
1018+
routeClass: createBCRoute(),
1019+
controllerClass: createBCRouteCtrller(
1020+
ALL_ROUTE_CRUMB_PROPS['tr-b-root']
1021+
),
1022+
},
1023+
{
1024+
routeName: 'tr-b-root',
1025+
routeClass: createBCRoute(),
1026+
controllerClass: createBCRouteCtrller({}, true),
1027+
template: hbs`
1028+
<AkStack @spacing="1" @direction="column" class="px-2" data-test-rootBTemplate-container>
1029+
Root B
1030+
1031+
<AkLink @route="authenticated.tr-b-root.parent-with-model" @model="1" data-test-linkToRootBParentWithModel1>
1032+
Link to Root B - Parent With Model 1
1033+
</AkLink>
1034+
1035+
<AkLink @route="authenticated.tr-b-root.parent-with-model" @models={{array 2}} data-test-linkToRootBParentWithModel2>
1036+
Link to Root B - Parent With Model 2
1037+
</AkLink>
1038+
1039+
{{outlet}}
1040+
</AkStack>
1041+
`,
1042+
},
1043+
{
1044+
routeName: 'tr-b-root/parent-with-model',
1045+
routeClass: createBCRoute(),
1046+
controllerClass: ParentWithModelController,
1047+
template: hbs`
1048+
<AkStack @spacing="1" @direction="column" class="px-2 my-2" data-test-rootAParentBTemplate-container>
1049+
Root B - Parent With Model - {{@model.id}}
1050+
1051+
<AkDivider @color='dark' />
1052+
1053+
<AkStack @spacing="1" @direction="column">
1054+
Parent With Model ({{@model.id}}) - Route Breadcrumb Items
1055+
1056+
<AkBreadcrumbs::AutoTrail />
1057+
</AkStack>
1058+
1059+
<AkLink @route="authenticated.tr-b-root.parent-with-model.child" @models={{array @model.id}} data-test-LinkToRootBParentWithModelChild>
1060+
Link to Parent With Model ({{@model.id}}) Child
1061+
</AkLink>
1062+
1063+
{{outlet}}
1064+
</AkStack>
1065+
`,
1066+
},
1067+
];
1068+
1069+
routesConfig.forEach((route) => setupRoute(this.owner, route));
1070+
1071+
// Start of test
1072+
await visit('/tr-b-root');
1073+
1074+
assert.strictEqual(currentURL(), '/tr-b-root', 'Route is at Root B');
1075+
1076+
assert.dom('[data-test-linkToRootBParentWithModel1]').exists();
1077+
assert.dom('[data-test-linkToRootBParentWithModel2]').exists();
1078+
1079+
// Go to route with model with ID of 1
1080+
await click('[data-test-linkToRootBParentWithModel1]');
1081+
1082+
const akBreadcrumbsService = this.owner.lookup('service:ak-breadcrumbs');
1083+
1084+
let expectedCrumbs = [
1085+
ALL_ROUTE_CRUMB_PROPS['tr-b-root'],
1086+
{
1087+
...ALL_ROUTE_CRUMB_PROPS['tr-b-root/parent-with-model'],
1088+
models: [1],
1089+
},
1090+
];
1091+
1092+
doBreadcrumbItemsCompare(
1093+
akBreadcrumbsService.breadcrumbItems,
1094+
expectedCrumbs,
1095+
assert
1096+
);
1097+
1098+
// Get router service
1099+
const router = this.owner.lookup('service:router');
1100+
1101+
// Reset router namespace simulates a window reload
1102+
router._router.reset();
1103+
1104+
const routeHandler = (transition) => {
1105+
if (transition.to.name === 'authenticated.tr-b-root.parent-with-model') {
1106+
// Ensure that routeFrom is null. Similar to a page refresh
1107+
// eslint-disable-next-line qunit/no-conditional-assertions
1108+
assert.strictEqual(transition.from, null);
1109+
}
1110+
};
1111+
1112+
router.on('routeWillChange', routeHandler);
1113+
1114+
// Go to parent route with model with ID of 2
1115+
await visit('/tr-b-root/parent-with-model/2');
1116+
1117+
// Defaults to fallback crumbs
1118+
doBreadcrumbItemsCompare(
1119+
akBreadcrumbsService.breadcrumbItems,
1120+
parentWithModelRouteFallbackCrumbs(2),
1121+
assert
1122+
);
1123+
});
9951124
});

0 commit comments

Comments
 (0)