1 |
|
2 |
|
3 | const { prepareESLint, lint } = require("../../test_utils");
|
4 |
|
5 | const engine = prepareESLint("recommended");
|
6 |
|
7 | it("Warns on console.log", async () => {
|
8 | const result = await lint(
|
9 | engine,
|
10 | `
|
11 | const foo = window;
|
12 |
|
13 | // Use a TypeScript 3.7 feature to make sure it works
|
14 | if (foo?.bar?.baz) {
|
15 | console.log(foo.bar.baz);
|
16 | }
|
17 | `,
|
18 | "file.ts"
|
19 | );
|
20 |
|
21 | expect(result.messages).toMatchSnapshot();
|
22 | expect(result.warningCount).toBe(1);
|
23 | expect(result.errorCount).toBe(0);
|
24 | });
|
25 |
|
26 | it("Uses sonar plugin", async () => {
|
27 | const result = await lint(
|
28 | engine,
|
29 | `
|
30 | /* global openWindow, closeWindow, moveWindowToTheBackground */
|
31 |
|
32 | function changeWindow(param: number) {
|
33 | if (param === 1) {
|
34 | openWindow();
|
35 | } else if (param === 2) {
|
36 | closeWindow();
|
37 | } else if (param === 1) {
|
38 | // Noncompliant ^
|
39 | moveWindowToTheBackground();
|
40 | }
|
41 | }
|
42 | `,
|
43 | "file.ts"
|
44 | );
|
45 |
|
46 | expect(result.messages).toMatchSnapshot();
|
47 | expect(result.warningCount).toBe(0);
|
48 | expect(result.errorCount).toBe(2);
|
49 | });
|
50 |
|
51 | it("Works with complex types", async () => {
|
52 | const result = await lint(
|
53 | engine,
|
54 | `
|
55 | import * as React from "react";
|
56 |
|
57 | type Writeable<T> = { -readonly [P in keyof T]-?: T[P] };
|
58 |
|
59 | type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
60 |
|
61 | function assignRef<T>(ref: T, setter: React.Ref<T>) {
|
62 | if (!setter || !ref) {
|
63 | return;
|
64 | }
|
65 |
|
66 | if (typeof setter === "function") {
|
67 | setter(ref);
|
68 | return;
|
69 | }
|
70 |
|
71 | if (setter.hasOwnProperty("current")) {
|
72 | (setter as Writeable<React.RefObject<T>>).current = ref;
|
73 | return;
|
74 | }
|
75 |
|
76 | throw new Error(
|
77 | "Your ref must be a function or an object created with React.createRef"
|
78 | );
|
79 | }
|
80 |
|
81 | export type triggerFunction = (options: {
|
82 | isOpen: boolean;
|
83 | caret: React.ReactNode;
|
84 | props: Record<string, unknown>;
|
85 | }) => React.ReactNode;
|
86 |
|
87 | export interface ButtonGroupProps extends React.HTMLAttributes<HTMLDivElement> {
|
88 | innerRef?: React.Ref<HTMLDivElement>;
|
89 | }
|
90 |
|
91 | export interface SplitButtonProps extends Omit<ButtonGroupProps, "innerRef"> {
|
92 | other: React.ReactNode;
|
93 | open?: boolean;
|
94 | trigger: React.ReactNode | triggerFunction;
|
95 |
|
96 | /**
|
97 | * Ref to get the component
|
98 | */
|
99 | innerRef?: React.Ref<HTMLElement>;
|
100 | }
|
101 |
|
102 | export interface SplitButtonState {
|
103 | open?: boolean;
|
104 | }
|
105 |
|
106 | export default class SplitButton extends React.Component<
|
107 | SplitButtonProps,
|
108 | SplitButtonState
|
109 | > {
|
110 | constructor(props) {
|
111 | super(props);
|
112 |
|
113 | this.state = {
|
114 | open: props.open || false
|
115 | };
|
116 | }
|
117 |
|
118 | private target: Element;
|
119 |
|
120 | ref = node => {
|
121 | this.target = getElement(node);
|
122 | assignRef(this.target, this.props.innerRef);
|
123 | };
|
124 |
|
125 | render(trigger) {
|
126 | const { trigger } = this.props;
|
127 | if (typeof trigger !== "function") {
|
128 | // eslint-disable-next-line @swissquote/swissquote/react/jsx-handler-names
|
129 | return <button innerRef={this.ref}>{trigger}</button>;
|
130 | }
|
131 |
|
132 | return (trigger as triggerFunction)({
|
133 | props: { innerRef: this.ref },
|
134 | isOpen: this.state.open,
|
135 | caret: <span className={this.props.classes("Caret")} />
|
136 | });
|
137 | }
|
138 | }
|
139 | `,
|
140 | "Component.tsx"
|
141 | );
|
142 |
|
143 | expect(result.messages).toMatchSnapshot();
|
144 | expect(result.warningCount).toBe(0);
|
145 | expect(result.errorCount).toBe(0);
|
146 | });
|