js-routes 2.0.8 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/routes.ts CHANGED
@@ -3,15 +3,51 @@
3
3
  * Based on Rails RubyVariables.RAILS_VERSION routes of RubyVariables.APP_CLASS
4
4
  */
5
5
 
6
- type RouteParameter = unknown;
7
- type RouteParameters = Record<string, RouteParameter>;
8
- type Serializer = (value: unknown) => string;
9
- type RouteHelper = {
10
- (...args: RouteParameter[]): string;
6
+ type Optional<T> = { [P in keyof T]?: T[P] | null };
7
+ type BaseRouteParameter = string | boolean | Date | number;
8
+ type MethodRouteParameter = BaseRouteParameter | (() => BaseRouteParameter);
9
+ type ModelRouteParameter =
10
+ | { id: MethodRouteParameter }
11
+ | { to_param: MethodRouteParameter }
12
+ | { toParam: MethodRouteParameter };
13
+ type RequiredRouteParameter = BaseRouteParameter | ModelRouteParameter;
14
+ type OptionalRouteParameter = undefined | null | RequiredRouteParameter;
15
+ type QueryRouteParameter =
16
+ | OptionalRouteParameter
17
+ | QueryRouteParameter[]
18
+ | { [k: string]: QueryRouteParameter };
19
+ type RouteParameters = Record<string, QueryRouteParameter>;
20
+
21
+ type Serializable = Record<string, unknown>;
22
+ type Serializer = (value: Serializable) => string;
23
+ type RouteHelperExtras = {
11
24
  requiredParams(): string[];
12
25
  toString(): string;
13
26
  };
14
27
 
28
+ type RequiredParameters<T extends number> = T extends 1
29
+ ? [RequiredRouteParameter]
30
+ : T extends 2
31
+ ? [RequiredRouteParameter, RequiredRouteParameter]
32
+ : T extends 3
33
+ ? [RequiredRouteParameter, RequiredRouteParameter, RequiredRouteParameter]
34
+ : T extends 4
35
+ ? [
36
+ RequiredRouteParameter,
37
+ RequiredRouteParameter,
38
+ RequiredRouteParameter,
39
+ RequiredRouteParameter
40
+ ]
41
+ : RequiredRouteParameter[];
42
+
43
+ type RouteHelperOptions<T extends string> = RouteOptions &
44
+ Optional<Record<T, OptionalRouteParameter>>;
45
+
46
+ type RouteHelper<T extends number = number, U extends string = string> = ((
47
+ ...args: [...RequiredParameters<T>, RouteHelperOptions<U>]
48
+ ) => string) &
49
+ RouteHelperExtras;
50
+
15
51
  type RouteHelpers = Record<string, RouteHelper>;
16
52
 
17
53
  type Configuration = {
@@ -21,7 +57,6 @@ type Configuration = {
21
57
  serializer: Serializer;
22
58
  };
23
59
 
24
- type Optional<T> = { [P in keyof T]?: T[P] | null };
25
60
  interface RouterExposedMethods {
26
61
  config(): Configuration;
27
62
  configure(arg: Partial<Configuration>): Configuration;
@@ -32,14 +67,16 @@ type KeywordUrlOptions = Optional<{
32
67
  host: string;
33
68
  protocol: string;
34
69
  subdomain: string;
35
- port: string;
70
+ port: string | number;
36
71
  anchor: string;
37
72
  trailing_slash: boolean;
38
73
  }>;
39
74
 
40
- type PartsTable = Record<string, { r?: boolean; d?: unknown }>;
75
+ type RouteOptions = KeywordUrlOptions & RouteParameters;
76
+
77
+ type PartsTable = Record<string, { r?: boolean; d?: OptionalRouteParameter }>;
41
78
 
42
- type ModuleType = "CJS" | "AMD" | "UMD" | "ESM" | "NIL";
79
+ type ModuleType = "CJS" | "AMD" | "UMD" | "ESM" | "DTS" | "NIL";
43
80
 
44
81
  declare const RubyVariables: {
45
82
  PREFIX: string;
@@ -92,8 +129,9 @@ RubyVariables.WRAPPER(
92
129
  }[keyof RouteNodes];
93
130
 
94
131
  const Root = that;
132
+ const isBroswer = typeof window !== "undefined";
95
133
  type ModuleDefinition = {
96
- define: (routes: unknown) => void;
134
+ define: (routes: RouterExposedMethods) => void;
97
135
  isSupported: () => boolean;
98
136
  };
99
137
  const ModuleReferences: Record<ModuleType, ModuleDefinition> = {
@@ -152,7 +190,16 @@ RubyVariables.WRAPPER(
152
190
  Utils.namespace(Root, RubyVariables.NAMESPACE, routes);
153
191
  },
154
192
  isSupported() {
155
- return !!Root;
193
+ return !RubyVariables.NAMESPACE || !!Root;
194
+ },
195
+ },
196
+ DTS: {
197
+ // Acts the same as ESM
198
+ define(routes) {
199
+ ModuleReferences.ESM.define(routes);
200
+ },
201
+ isSupported() {
202
+ return ModuleReferences.ESM.isSupported();
156
203
  },
157
204
  },
158
205
  };
@@ -225,16 +272,16 @@ RubyVariables.WRAPPER(
225
272
  return result.join("&");
226
273
  }
227
274
 
228
- serialize(object: unknown): string {
275
+ serialize(object: Serializable): string {
229
276
  return this.configuration.serializer(object);
230
277
  }
231
278
 
232
279
  extract_options(
233
280
  number_of_params: number,
234
- args: RouteParameter[]
281
+ args: OptionalRouteParameter[]
235
282
  ): {
236
- args: RouteParameter[];
237
- options: KeywordUrlOptions & RouteParameters;
283
+ args: OptionalRouteParameter[];
284
+ options: RouteOptions;
238
285
  } {
239
286
  const last_el = args[args.length - 1];
240
287
  if (
@@ -247,32 +294,27 @@ RubyVariables.WRAPPER(
247
294
  }
248
295
  return {
249
296
  args: args.slice(0, args.length - 1),
250
- options: last_el as KeywordUrlOptions & RouteParameters,
297
+ options: (last_el as any) as RouteOptions,
251
298
  };
252
299
  } else {
253
300
  return { args, options: {} };
254
301
  }
255
302
  }
256
303
 
257
- looks_like_serialized_model(
258
- object: any
259
- ): object is
260
- | { id: unknown }
261
- | { to_param: unknown }
262
- | { toParam: unknown } {
304
+ looks_like_serialized_model(object: any): object is ModelRouteParameter {
263
305
  return (
264
306
  this.is_object(object) &&
265
- !object[this.configuration.special_options_key] &&
307
+ !(this.configuration.special_options_key in object) &&
266
308
  ("id" in object || "to_param" in object || "toParam" in object)
267
309
  );
268
310
  }
269
311
 
270
- path_identifier(object: unknown): string {
312
+ path_identifier(object: QueryRouteParameter): string {
271
313
  const result = this.unwrap_path_identifier(object);
272
314
  return this.is_nullable(result) || result === false ? "" : "" + result;
273
315
  }
274
316
 
275
- unwrap_path_identifier(object: any): unknown {
317
+ unwrap_path_identifier(object: QueryRouteParameter): unknown {
276
318
  let result: any = object;
277
319
  if (!this.is_object(object)) {
278
320
  return object;
@@ -293,7 +335,7 @@ RubyVariables.WRAPPER(
293
335
  parts: string[],
294
336
  required_params: string[],
295
337
  default_options: RouteParameters,
296
- call_arguments: RouteParameter[]
338
+ call_arguments: OptionalRouteParameter[]
297
339
  ): {
298
340
  keyword_parameters: KeywordUrlOptions;
299
341
  query_parameters: RouteParameters;
@@ -307,7 +349,9 @@ RubyVariables.WRAPPER(
307
349
  throw new Error("Too many parameters provided for path");
308
350
  }
309
351
  let use_all_parts = args.length > required_params.length;
310
- const parts_options: RouteParameters = {};
352
+ const parts_options: RouteParameters = {
353
+ ...this.configuration.default_url_options,
354
+ };
311
355
  for (const key in options) {
312
356
  const value = options[key];
313
357
  if (!hasProp(options, key)) continue;
@@ -357,7 +401,7 @@ RubyVariables.WRAPPER(
357
401
  default_options: RouteParameters,
358
402
  route: RouteTree,
359
403
  absolute: boolean,
360
- args: RouteParameter[]
404
+ args: OptionalRouteParameter[]
361
405
  ): string {
362
406
  const {
363
407
  keyword_parameters,
@@ -467,9 +511,9 @@ RubyVariables.WRAPPER(
467
511
  }
468
512
 
469
513
  encode_segment(segment: string): string {
470
- return segment.replace(UriEncoderSegmentRegex, function (str) {
471
- return encodeURIComponent(str);
472
- });
514
+ return segment.replace(UriEncoderSegmentRegex, (str) =>
515
+ encodeURIComponent(str)
516
+ );
473
517
  }
474
518
 
475
519
  is_optional_node(node: NodeTypes): boolean {
@@ -550,7 +594,7 @@ RubyVariables.WRAPPER(
550
594
  default_options[part] = value;
551
595
  }
552
596
  }
553
- const result = (...args: RouteParameter[]): string => {
597
+ const result = (...args: OptionalRouteParameter[]): string => {
554
598
  return this.build_route(
555
599
  parts,
556
600
  required_params,
@@ -564,7 +608,7 @@ RubyVariables.WRAPPER(
564
608
  result.toString = () => {
565
609
  return this.build_path_spec(route_spec);
566
610
  };
567
- return result;
611
+ return result as any;
568
612
  }
569
613
 
570
614
  route_url(route_defaults: KeywordUrlOptions): string {
@@ -583,31 +627,18 @@ RubyVariables.WRAPPER(
583
627
  return protocol + "://" + subdomain + hostname + port;
584
628
  }
585
629
 
586
- has_location(): boolean {
587
- return this.is_not_nullable(window) && !!window.location;
588
- }
589
-
590
- current_host(): string | null {
591
- if (this.has_location()) {
592
- return window.location.hostname;
593
- } else {
594
- return null;
595
- }
630
+ current_host(): string {
631
+ return (isBroswer && window?.location?.hostname) || "";
596
632
  }
597
633
 
598
634
  current_protocol(): string {
599
- if (this.has_location() && window.location.protocol !== "") {
600
- return window.location.protocol.replace(/:$/, "");
601
- } else {
602
- return "http";
603
- }
635
+ return (
636
+ (isBroswer && window?.location?.protocol?.replace(/:$/, "")) || "http"
637
+ );
604
638
  }
639
+
605
640
  current_port(): string {
606
- if (this.has_location() && window.location.port !== "") {
607
- return window.location.port;
608
- } else {
609
- return "";
610
- }
641
+ return (isBroswer && window?.location?.port) || "";
611
642
  }
612
643
 
613
644
  is_object(value: unknown): value is Record<string, unknown> {
@@ -633,17 +664,17 @@ RubyVariables.WRAPPER(
633
664
  object: any,
634
665
  namespace: string | null | undefined,
635
666
  routes: unknown
636
- ): unknown {
667
+ ): void {
637
668
  const parts = namespace?.split(".") || [];
638
669
  if (parts.length === 0) {
639
- return routes;
670
+ return;
640
671
  }
641
672
  for (let index = 0; index < parts.length; index++) {
642
673
  const part = parts[index];
643
674
  if (index < parts.length - 1) {
644
675
  object = object[part] || (object[part] = {});
645
676
  } else {
646
- return (object[part] = routes);
677
+ object[part] = routes;
647
678
  }
648
679
  }
649
680
  }
@@ -694,7 +725,7 @@ RubyVariables.WRAPPER(
694
725
  config: (): Configuration => {
695
726
  return Utils.config();
696
727
  },
697
- serialize: (object: unknown): string => {
728
+ serialize: (object: Serializable): string => {
698
729
  return Utils.serialize(object);
699
730
  },
700
731
  ...RubyVariables.ROUTES_OBJECT,
@@ -1,8 +1,14 @@
1
1
  namespace :js do
2
- desc "Make a js file that will have functions that will return restful routes/urls."
2
+ desc "Make a js file with all rails route URL helpers"
3
3
  task routes: :environment do
4
4
  require "js-routes"
5
-
6
5
  JsRoutes.generate!
7
6
  end
7
+
8
+ namespace :routes do
9
+ desc "Make a js file with all rails route URL helpers and typescript definitions for them"
10
+ task typescript: "js:routes" do
11
+ JsRoutes.definitions!
12
+ end
13
+ end
8
14
  end
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ module: {
3
+ rules: [
4
+ {
5
+ test: /\.erb$/,
6
+ enforce: 'pre',
7
+ loader: 'rails-erb-loader'
8
+ },
9
+ ]
10
+ }
11
+ };
@@ -0,0 +1,5 @@
1
+ JsRoutes.setup do |c|
2
+ # Setup your JS module system:
3
+ # ESM, CJS, AMD, UMD or nil
4
+ # c.module_type = "ESM"
5
+ end
@@ -0,0 +1 @@
1
+ <%= JsRoutes.generate %>
@@ -3,11 +3,12 @@ require "spec_helper"
3
3
  describe JsRoutes, "compatibility with AMD/require.js" do
4
4
 
5
5
  before(:each) do
6
- evaljs("window.GlobalCheck = {};")
7
- evaljs("window.define = function (requirs, callback) { window.GlobalCheck['js-routes'] = callback.call(this); return window.GlobalCheck['js-routes']; };")
8
- evaljs("window.define.amd = { jQuery: true };")
6
+ evaljs("var global = this;", {force: true})
7
+ evaljs("global.GlobalCheck = {};")
8
+ evaljs("global.define = function (requirs, callback) { global.GlobalCheck['js-routes'] = callback.call(this); return global.GlobalCheck['js-routes']; };")
9
+ evaljs("global.define.amd = { jQuery: true };")
9
10
  strRequire =<<EOF
10
- window.require = function (r, callback) {
11
+ global.require = function (r, callback) {
11
12
  var allArgs, i;
12
13
 
13
14
  allArgs = (function() {
@@ -15,7 +16,7 @@ describe JsRoutes, "compatibility with AMD/require.js" do
15
16
  _results = [];
16
17
  for (_i = 0, _len = r.length; _i < _len; _i++) {
17
18
  i = r[_i];
18
- _results.push(window.GlobalCheck[i]);
19
+ _results.push(global.GlobalCheck[i]);
19
20
  }
20
21
  return _results;
21
22
  })();
@@ -0,0 +1,114 @@
1
+ /**
2
+ * File generated by js-routes RubyVariables.GEM_VERSION
3
+ * Based on Rails RubyVariables.RAILS_VERSION routes of RubyVariables.APP_CLASS
4
+ */
5
+ declare type Optional<T> = {
6
+ [P in keyof T]?: T[P] | null;
7
+ };
8
+ declare type BaseRouteParameter = string | boolean | Date | number;
9
+ declare type MethodRouteParameter = BaseRouteParameter | (() => BaseRouteParameter);
10
+ declare type ModelRouteParameter = {
11
+ id: MethodRouteParameter;
12
+ } | {
13
+ to_param: MethodRouteParameter;
14
+ } | {
15
+ toParam: MethodRouteParameter;
16
+ };
17
+ declare type RequiredRouteParameter = BaseRouteParameter | ModelRouteParameter;
18
+ declare type OptionalRouteParameter = undefined | null | RequiredRouteParameter;
19
+ declare type QueryRouteParameter = OptionalRouteParameter | QueryRouteParameter[] | {
20
+ [k: string]: QueryRouteParameter;
21
+ };
22
+ declare type RouteParameters = Record<string, QueryRouteParameter>;
23
+ declare type Serializable = Record<string, unknown>;
24
+ declare type Serializer = (value: Serializable) => string;
25
+ declare type RouteHelperExtras = {
26
+ requiredParams(): string[];
27
+ toString(): string;
28
+ };
29
+ declare type RequiredParameters<T extends number> = T extends 1 ? [RequiredRouteParameter] : T extends 2 ? [RequiredRouteParameter, RequiredRouteParameter] : T extends 3 ? [RequiredRouteParameter, RequiredRouteParameter, RequiredRouteParameter] : T extends 4 ? [
30
+ RequiredRouteParameter,
31
+ RequiredRouteParameter,
32
+ RequiredRouteParameter,
33
+ RequiredRouteParameter
34
+ ] : RequiredRouteParameter[];
35
+ declare type RouteHelperOptions<T extends string> = RouteOptions & Optional<Record<T, OptionalRouteParameter>>;
36
+ declare type RouteHelper<T extends number = number, U extends string = string> = ((...args: [...RequiredParameters<T>, RouteHelperOptions<U>]) => string) & RouteHelperExtras;
37
+ declare type RouteHelpers = Record<string, RouteHelper>;
38
+ declare type Configuration = {
39
+ prefix: string;
40
+ default_url_options: RouteParameters;
41
+ special_options_key: string;
42
+ serializer: Serializer;
43
+ };
44
+ interface RouterExposedMethods {
45
+ config(): Configuration;
46
+ configure(arg: Partial<Configuration>): Configuration;
47
+ serialize: Serializer;
48
+ }
49
+ declare type KeywordUrlOptions = Optional<{
50
+ host: string;
51
+ protocol: string;
52
+ subdomain: string;
53
+ port: string | number;
54
+ anchor: string;
55
+ trailing_slash: boolean;
56
+ }>;
57
+ declare type RouteOptions = KeywordUrlOptions & RouteParameters;
58
+ declare type PartsTable = Record<string, {
59
+ r?: boolean;
60
+ d?: OptionalRouteParameter;
61
+ }>;
62
+ declare type ModuleType = "CJS" | "AMD" | "UMD" | "ESM" | "DTS" | "NIL";
63
+ declare const RubyVariables: {
64
+ PREFIX: string;
65
+ DEPRECATED_GLOBBING_BEHAVIOR: boolean;
66
+ SPECIAL_OPTIONS_KEY: string;
67
+ DEFAULT_URL_OPTIONS: RouteParameters;
68
+ SERIALIZER: Serializer;
69
+ NAMESPACE: string;
70
+ ROUTES_OBJECT: RouteHelpers;
71
+ MODULE_TYPE: ModuleType;
72
+ WRAPPER: <T>(callback: T) => T;
73
+ };
74
+ declare const define: undefined | (((arg: unknown[], callback: () => unknown) => void) & {
75
+ amd?: unknown;
76
+ });
77
+ declare const module: {
78
+ exports: any;
79
+ } | undefined;
80
+ export const configure: RouterExposedMethods['configure'];
81
+
82
+ export const config: RouterExposedMethods['config'];
83
+
84
+ export const serialize: RouterExposedMethods['serialize'];
85
+
86
+ /**
87
+ * Generates rails route to
88
+ * /inboxes/:inbox_id/messages/:message_id/attachments/:id(.:format)
89
+ * @param {any} inbox_id
90
+ * @param {any} message_id
91
+ * @param {any} id
92
+ * @param {object | undefined} options
93
+ * @returns {string} route path
94
+ */
95
+ export const inbox_message_attachment_path: ((
96
+ inbox_id: RequiredRouteParameter,
97
+ message_id: RequiredRouteParameter,
98
+ id: RequiredRouteParameter,
99
+ options?: {format?: OptionalRouteParameter} & RouteOptions
100
+ ) => string) & RouteHelperExtras;
101
+
102
+ /**
103
+ * Generates rails route to
104
+ * /inboxes(.:format)
105
+ * @param {object | undefined} options
106
+ * @returns {string} route path
107
+ */
108
+ export const inboxes_path: ((
109
+ options?: {format?: OptionalRouteParameter} & RouteOptions
110
+ ) => string) & RouteHelperExtras;
111
+
112
+ // By some reason this line prevents all types in a file
113
+ // from being automatically exported
114
+ export {};
@@ -0,0 +1,56 @@
1
+ import {
2
+ inbox_message_attachment_path,
3
+ inboxes_path,
4
+ serialize,
5
+ configure,
6
+ config,
7
+ } from "./routes.spec";
8
+
9
+ // Route Helpers
10
+ inboxes_path();
11
+ inboxes_path({
12
+ locale: "en",
13
+ search: {
14
+ q: "ukraine",
15
+ page: 3,
16
+ keywords: ["large", "small", { advanced: true }],
17
+ },
18
+ });
19
+
20
+ inbox_message_attachment_path(1, "2", true);
21
+ inbox_message_attachment_path(
22
+ { id: 1 },
23
+ { to_param: () => "2" },
24
+ { toParam: () => true }
25
+ );
26
+ inbox_message_attachment_path(1, "2", true, { format: "json" });
27
+ inboxes_path.toString();
28
+ inboxes_path.requiredParams();
29
+
30
+ // serialize test
31
+ const SerializerArgument = {
32
+ locale: "en",
33
+ search: {
34
+ q: "ukraine",
35
+ page: 3,
36
+ keywords: ["large", "small", { advanced: true }],
37
+ },
38
+ };
39
+ serialize(SerializerArgument);
40
+ config().serializer(SerializerArgument);
41
+
42
+ // configure test
43
+ configure({
44
+ default_url_options: { port: 1, host: null },
45
+ prefix: "",
46
+ special_options_key: "_options",
47
+ serializer: (value) => JSON.stringify(value),
48
+ });
49
+
50
+ // config tests
51
+ const Config = config();
52
+ console.log(
53
+ Config.prefix,
54
+ Config.default_url_options,
55
+ Config.special_options_key
56
+ );
@@ -0,0 +1,111 @@
1
+
2
+ require "active_support/core_ext/string/strip"
3
+ require "fileutils"
4
+ require "open3"
5
+ require "spec_helper"
6
+
7
+ describe JsRoutes, "compatibility with DTS" do
8
+
9
+ OPTIONS = {module_type: 'DTS', include: [/^inboxes$/, /^inbox_message_attachment$/]}
10
+ let(:extra_options) do
11
+ {}
12
+ end
13
+
14
+ let(:generated_js) do
15
+ JsRoutes.generate({**OPTIONS, **extra_options})
16
+ end
17
+
18
+ context "when file is generated" do
19
+ let(:dir_name) do
20
+ File.expand_path(__dir__ + "/dts")
21
+ end
22
+
23
+ let(:file_name) do
24
+ dir_name + "/routes.spec.d.ts"
25
+ end
26
+
27
+ before do
28
+ FileUtils.mkdir_p(dir_name)
29
+ File.write(file_name, generated_js)
30
+ end
31
+
32
+ it "has no compile errors", :slow do
33
+ command = "yarn tsc --strict --noEmit -p spec/tsconfig.json"
34
+ stdout, stderr, status = Open3.capture3(command)
35
+ expect(stderr).to eq("")
36
+ expect(stdout).to include("Done in ")
37
+ expect(status).to eq(0)
38
+ end
39
+ end
40
+
41
+ context "when camel case is enabled" do
42
+ let(:extra_options) { {camel_case: true} }
43
+
44
+ it "camelizes route name and arguments" do
45
+
46
+ expect(generated_js).to include(<<-DOC.rstrip)
47
+ /**
48
+ * Generates rails route to
49
+ * /inboxes/:inbox_id/messages/:message_id/attachments/:id(.:format)
50
+ * @param {any} inboxId
51
+ * @param {any} messageId
52
+ * @param {any} id
53
+ * @param {object | undefined} options
54
+ * @returns {string} route path
55
+ */
56
+ export const inboxMessageAttachmentPath: ((
57
+ inboxId: RequiredRouteParameter,
58
+ messageId: RequiredRouteParameter,
59
+ id: RequiredRouteParameter,
60
+ options?: {format?: OptionalRouteParameter} & RouteOptions
61
+ ) => string) & RouteHelperExtras;
62
+ DOC
63
+ end
64
+ end
65
+
66
+ it "exports route helpers" do
67
+ expect(generated_js).to include(<<-DOC.rstrip)
68
+ /**
69
+ * Generates rails route to
70
+ * /inboxes(.:format)
71
+ * @param {object | undefined} options
72
+ * @returns {string} route path
73
+ */
74
+ export const inboxes_path: ((
75
+ options?: {format?: OptionalRouteParameter} & RouteOptions
76
+ ) => string) & RouteHelperExtras;
77
+ DOC
78
+ expect(generated_js).to include(<<-DOC.rstrip)
79
+ /**
80
+ * Generates rails route to
81
+ * /inboxes/:inbox_id/messages/:message_id/attachments/:id(.:format)
82
+ * @param {any} inbox_id
83
+ * @param {any} message_id
84
+ * @param {any} id
85
+ * @param {object | undefined} options
86
+ * @returns {string} route path
87
+ */
88
+ export const inbox_message_attachment_path: ((
89
+ inbox_id: RequiredRouteParameter,
90
+ message_id: RequiredRouteParameter,
91
+ id: RequiredRouteParameter,
92
+ options?: {format?: OptionalRouteParameter} & RouteOptions
93
+ ) => string) & RouteHelperExtras
94
+ DOC
95
+ end
96
+
97
+ it "exports utility methods" do
98
+ expect(generated_js).to include("export const serialize: RouterExposedMethods['serialize'];")
99
+ end
100
+
101
+ it "prevents all types from automatic export" do
102
+ expect(generated_js).to include("export {};")
103
+ end
104
+
105
+ describe "compiled javascript asset" do
106
+ subject { ERB.new(File.read("app/assets/javascripts/js-routes.js.erb")).result(binding) }
107
+ it "should have js routes code" do
108
+ is_expected.to include("export const inbox_message_path = __jsr.r(")
109
+ end
110
+ end
111
+ end