Passed
Push — main ( 3c28e5...05f9bd )
by Andrii
02:01
created

src/defs.test.ts   A

Complexity

Total Complexity 5
Complexity/F 1

Size

Lines of Code 320
Function Count 5

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 241
dl 0
loc 320
rs 10
c 0
b 0
f 0
wmc 5
mnd 0
bc 0
fnc 5
bpm 0
cpm 1
noi 0

5 Functions

Rating   Name   Duplication   Size   Complexity  
A defs.test.ts ➔ RWithout 0 1 1
A defs.test.ts ➔ RSome 0 1 1
A defs.test.ts ➔ Functional 0 1 1
A defs.test.ts ➔ RWrong 0 1 1
A defs.test.ts ➔ RProps 0 1 1
1
import {
2
  Component,
3
  PureComponent
4
} from "react"
5
import type {
6
  ClassNamed,
7
  ClassHash,
8
  ReactRelated,
9
  GetProps,
10
  ClassNamesProperty,
11
  ClassNames
12
} from "./defs"
13
14
type Props = ClassNames<true, ClassNamesProperty<{props: ClassHash}>>
15
function Functional(_: ClassNames<ClassNamesProperty<{functional: ClassHash}>>) { return null }
16
class ClassComponent extends Component<ClassNames<ClassNamesProperty<{component: ClassHash; comp0: ClassHash}>>> {}
17
class ClassPureComponent extends PureComponent<ClassNames<ClassNamesProperty<{pureComponent: ClassHash}>>> {}
18
19
describe("ClassNames", () => {
20
  describe("direct", () => {
21
    it("<true>", () => {
22
      const suites: Record<string, ClassNames<true>> = {
23
        "className only": {className: ""},
24
        //@ts-expect-error Property 'className' is missing
25
        "empty object"
26
        : {},
27
        "classnames only": {
28
          //@ts-expect-error Object literal may only specify known properties, but 'classnames' does not exist
29
          classnames: {}
30
        },
31
        "className and classnames": {
32
          className: "",
33
          //@ts-expect-error Object literal may only specify known properties, but 'classnames' does not exist
34
          classnames: {}
35
        }
36
      }
37
      expect(suites).toBeInstanceOf(Object)
38
    })
39
  
40
    it("<{class1, class2}>", () => {
41
      const suites: Record<string, ClassNames<{classnames: {class1: ClassHash; class2: ClassHash}}>> = {
42
        "omitted": {
43
          //@ts-expect-error ReactRelated
44
          classnames: {
45
            class1: undefined
46
          }
47
        },
48
        "classnames only": {
49
          classnames: {class1: undefined, class2: undefined}
50
        },
51
        "className only": {
52
          //@ts-expect-error Object literal may only specify known properties, but 'className' does not exist
53
          className: ""
54
        },
55
        //@ts-expect-error Property 'classnames' is missing
56
        "empty object"
57
        : {},
58
        "className and classnames": {
59
          //@ts-expect-error Object literal may only specify known properties, but 'className' does not exist
60
          className: "",
61
          classnames: {class1: undefined, class2: undefined}
62
        }
63
      }
64
      expect(suites).toBeInstanceOf(Object)
65
    })
66
  
67
    it("<true, {class1, class2}>", () => {
68
      const suites: Record<string, ClassNames<true, {classnames: {class1: ClassHash; class2: ClassHash}}>> = {
69
        "className and classnames": {
70
          className: "",
71
          classnames: {class1: undefined, class2: undefined}
72
        },
73
        //@ts-expect-error Property 'className' is missing
74
        "classnames only": {
75
          classnames: {class1: undefined, class2: undefined}
76
        },
77
        //@ts-expect-error Property 'classnames' is missing
78
        "className only": {
79
          className: ""
80
        }
81
      }
82
      expect(suites).toBeInstanceOf(Object)
83
    })
84
  
85
    it("nothing to pick", () => {
86
      type NoClassNames = ClassNames<true>
87
      const suite1: Record<string, ClassNames<
88
        //@ts-expect-error
89
        NoClassNames,
90
        {classnames: {class1: ClassHash}},
91
        {classnames: {class1: ClassHash}}
92
      >> = {
93
        "nothing": {classnames: {class1: ""}}
94
      }
95
      const suite2: Record<string, ClassNames<
96
        {classnames: {class1: ClassHash}},
97
        {classnames: {class1: ClassHash}},
98
        //@ts-expect-error
99
        NoClassNames
100
      >> = {
101
        "nothing": {classnames: {class1: ""}}
102
      }
103
      expect({suite1, suite2}).toBeInstanceOf(Object)
104
    })
105
  })
106
107
  describe("from", () => {
108
    it("manually merge", () => {
109
      type AppClassNames = (
110
        ClassNamesProperty<{App: ClassHash}>
111
        & ClassNames<typeof ClassComponent>
112
        & ClassNames<typeof ClassPureComponent>
113
        & ClassNames<typeof Functional>
114
        & ClassNames<Props>
115
      );
116
    
117
      const suites: Record<string, AppClassNames["classnames"]> = {
118
        "exact": {
119
          App: undefined,
120
          component: undefined,
121
          comp0: undefined,
122
          functional: undefined,
123
          props: undefined,
124
          pureComponent: undefined
125
        },
126
        "redundant": {
127
          //@ts-expect-error Object literal may only specify known properties, and 'redundant' does not exist
128
          redundant: undefined,
129
          App: undefined,
130
          component: undefined,
131
          functional: undefined,
132
          props: undefined,
133
          pureComponent: undefined,
134
        },
135
        //@ts-expect-error Property 'App' is missing
136
        "missed App": {
137
          component: undefined,
138
          functional: undefined,
139
          props: undefined,
140
          pureComponent: undefined,
141
        },
142
        //@ts-expect-error Property 'component' is missing
143
        "missed component": {
144
          App: undefined,
145
          functional: undefined,
146
          props: undefined,
147
          pureComponent: undefined,
148
        },
149
        //@ts-expect-error Property 'pureComponent' is missing
150
        "missed pureComponent": {
151
          App: undefined,
152
          component: undefined,
153
          functional: undefined,
154
          props: undefined,
155
        },
156
        //@ts-expect-error Property 'functional' is missing 
157
        "missed functional": {
158
          App: undefined,
159
          component: undefined,
160
          props: undefined,
161
          pureComponent: undefined,
162
        },
163
        //@ts-expect-error Property 'props' is missing
164
        "missed props": {
165
          App: undefined,
166
          component: undefined,
167
          functional: undefined,
168
          pureComponent: undefined,
169
        }
170
      }
171
      
172
      expect(suites).toBeInstanceOf(Object)
173
    })
174
  
175
    it("multiple apply", () => {
176
      type AppClassNames = ClassNames<
177
          true,
178
          ClassNamesProperty<{App: ClassHash}>,
179
          typeof ClassComponent,
180
          typeof ClassPureComponent,
181
          typeof Functional,
182
          Props
183
      >;
184
  
185
      const suites: Record<string, AppClassNames["classnames"]> = {
186
        "exact": {
187
          App: undefined,
188
          component: undefined,
189
          comp0: undefined,
190
          functional: undefined,
191
          props: undefined,
192
          pureComponent: undefined
193
        }
194
      }
195
  
196
      expect(suites).toBeInstanceOf(Object)
197
    })
198
  })    
199
})
200
201
describe("ClassNamesProperty", () => {
202
  it("Free declaration", () => {
203
    type Props = ClassNamesProperty<{
204
      class1: ClassHash, class2: ClassHash
205
    }>
206
    const suites: Record<string, Props["classnames"]> = {
207
      "all setted": {
208
        class1: "class1",
209
        class2: undefined
210
      },
211
      "redundant": {
212
        class1: "class1",
213
        class2: undefined,
214
        //@ts-expect-error
215
        redundant: "redundant"
216
      },
217
      //@ts-expect-error
218
      "missed": {
219
        class1: "class1"
220
      },
221
      "wrong type": {
222
        class1: "class1",
223
        //@ts-expect-error
224
        class2: false
225
      }
226
    }
227
    expect(suites).toBeInstanceOf(Object)
228
  })
229
  
230
  it("Module based", () => {
231
    type CssModule = {
232
      App: ClassHash
233
      class1: ClassHash, class2: ClassHash
234
    }
235
236
    type Props = ClassNamesProperty<CssModule, {
237
      class1: ClassHash
238
      class2: ClassHash
239
      //TODO #12 Why no suggestion? Means - no rename effect
240
    }>
241
242
    type PropsWithWrong = ClassNamesProperty<CssModule,
243
      //@ts-expect-error
244
      {
245
        class1: ClassHash
246
        class3: ClassHash
247
      }
248
    >
249
    
250
    const suite4wrong: PropsWithWrong["classnames"] = {
251
        //@ts-expect-error Object literal may only specify known properties, but 'class3' does not exist
252
        class3: undefined,
253
    },
254
    suite: Props["classnames"] = {
255
      class1: "class1",
256
      class2: undefined
257
    }
258
    expect({suite4wrong, suite}).toBeInstanceOf(Object)
259
  })
260
})
261
262
263
describe("ReactRelated", () => {
264
  type Getter<T extends ReactRelated> = GetProps<T>
265
266
  type Without = ClassNamed
267
  type Wrong = ClassNamed & {classnames: string}
268
  type Some = ClassNamed & {classnames: Record<string, ClassHash>}
269
  type Props = ClassNamed & {classnames: {class1: ClassHash; class2: ClassHash;}}
270
271
  it("Component", () => {
272
    class RWithout extends Component<Without> {};
273
    class RWrong extends Component<Wrong> {};
274
    class RSome extends Component<Some> {};
275
    class RProps extends Component<Props> {};
276
277
    //@ts-expect-error
278
    type x =
279
    | Getter<typeof RProps>
280
    //@ts-expect-error
281
    type Res =
282
    //@ts-expect-error
283
    | Getter<typeof RWithout>
284
    //@ts-expect-error
285
    | Getter<typeof RWrong> 
286
    //Consider @ts-expect-error
287
    | Getter<typeof RSome>
288
    | Getter<typeof RProps>
289
    
290
    expect(true).toBe(true)
291
  })
292
293
  it("Function", () => {
294
    function RWithout(_: Without) {return null};
295
    function RWrong(_: Wrong) {return null};
296
    function RSome(_: Some) {return null};
297
    function RProps(_: Props) {return null};
298
299
    // type RF = (props: {classnames: any}) => ReactElement<any, any> | null
300
301
    // const ch1: Props extends {classnames: any} ? true : false = true
302
    // const ch2: Parameters<typeof RProps>[0] extends {classnames: any} ? true : false = true
303
    // const ch3: Parameters<typeof RProps>[0] extends Parameters<RF>[0] ? true : false = true
304
305
    //@ts-expect-error
306
    type Res =
307
    //TODO @ts-expect-error
308
    | Getter<typeof RWithout>
309
    //TODO @ts-expect-error
310
    | Getter<typeof RWrong>
311
    //Consider @ts-expect-error 
312
    | Getter<typeof RSome>
313
    | Getter<typeof RProps>
314
    
315
    expect(true).toBe(true)
316
  })
317
318
319
})
320