tests/cards/poll-card.test.ts   A
last analyzed

Complexity

Total Complexity 42
Complexity/F 0

Size

Lines of Code 130
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 42
eloc 103
mnd 42
bc 42
fnc 0
dl 0
loc 130
rs 9.0399
bpm 0
cpm 0
noi 0
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like tests/cards/poll-card.test.ts often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import {ClosableType, PollState} from '../../src/helpers/interfaces';
2
import PollCard from '../../src/cards/PollCard';
3
import {dummyAutoclosePollState, dummyLocalTimezone, dummyPollState} from '../dummy';
4
// @ts-ignore: unreasonable error
5
import voteCardJson from '../json/vote_card.json';
6
7
describe('PollCard', () => {
8
  it('should return a valid GoogleAppsCardV1Card object when create() is called', () => {
9
    const state: PollState = {
10
      topic: 'Test Topic',
11
      choices: ['Choice 1', 'Choice 2'],
12
      votes: {},
13
    };
14
    const pollCard = new PollCard(state, dummyLocalTimezone);
15
    const result = pollCard.create();
16
    expect(result).toBeDefined();
17
    expect(result.sections).toBeDefined();
18
  });
19
  it('should return dialog interaction if voteLimit is set more than 1', () => {
20
    const state: PollState = {
21
      topic: 'Test Topic',
22
      choices: ['Choice 1', 'Choice 2'],
23
      votes: {},
24
      voteLimit: 2,
25
    };
26
    const pollCard = new PollCard(state, dummyLocalTimezone);
27
    const result = pollCard.create();
28
    expect(result).toBeDefined();
29
    expect(result.sections).toBeDefined();
30
    expect(result.sections![1].widgets![0].decoratedText.button.onClick.action.interaction).toEqual('OPEN_DIALOG');
31
  });
32
33
  it('should add a header to the card when the topic is less than or equal to 40 characters', () => {
34
    const state: PollState = {
35
      topic: 'Test Topic',
36
      choices: ['Choice 1', 'Choice 2'],
37
      votes: {},
38
    };
39
    const pollCard = new PollCard(state, dummyLocalTimezone).create();
40
    expect(pollCard.header).toBeDefined();
41
  });
42
43
  it('should add a section header to the card when the topic is greater than 40 characters', () => {
44
    const state: PollState = {
45
      topic: 'This is a very long topic that exceeds the character limit',
46
      choices: ['Choice 1', 'Choice 2'],
47
      votes: {},
48
    };
49
    const pollCard = new PollCard(state, dummyLocalTimezone).create();
50
    expect(pollCard.header).toBeUndefined();
51
    expect(pollCard.sections![0].widgets![0].decoratedText.text).toEqual(state.topic);
52
  });
53
54
  it('should not add an "Add Option" button when optionable is false', () => {
55
    const state: PollState = {
56
      topic: 'Test Topic',
57
      choices: ['Choice 1', 'Choice 2'],
58
      votes: {},
59
      optionable: false,
60
      closedTime: 1,
61
    };
62
    const pollCard = new PollCard(state, dummyLocalTimezone).create();
63
    expect(pollCard.sections!.find((section) => section.widgets?.[0]?.buttonList?.buttons?.[0]?.text === 'Add Option')).
64
      toBeUndefined();
65
    const closeButton = pollCard.sections!.find((section) => section.widgets?.[0]?.buttonList?.buttons?.[0]?.disabled);
66
    // since closedTime < now the close button is disabled
67
    expect(closeButton.widgets?.[0]?.buttonList?.buttons?.[0]?.disabled).toEqual(true);
68
    const voteButton = pollCard.sections!.find((section) => {
69
      const button = section.widgets?.[0]?.decoratedText.button;
70
      return button?.text === 'vote' && button.disabled === true;
71
    });
72
    expect(voteButton).toBeDefined();
73
  });
74
75
  it('should not add any button when the type is UNCLOSEABLE and optionable is false', () => {
76
    const state: PollState = {
77
      topic: 'Test Topic',
78
      choices: ['Choice 1', 'Choice 2'],
79
      votes: {},
80
      optionable: false,
81
      type: ClosableType.UNCLOSEABLE,
82
    };
83
    const pollCard = new PollCard(state, dummyLocalTimezone).create();
84
    // since optionable
85
    expect(pollCard.sections!.find((section) => section.widgets?.[0]?.buttonList?.buttons?.[0]?.text === 'Add Option')).
86
      toBeUndefined();
87
    // because default if closable is not defined is true
88
    expect(pollCard.sections!.find((section) => section.widgets?.[0]?.buttonList?.buttons?.[1]?.text === 'Close Poll')).
89
      toBeUndefined();
90
  });
91
92
  it('should return a valid GoogleAppsCardV1Section object even when the votes array is undefined', () => {
93
    const state: PollState = {
94
      topic: 'Test Topic',
95
      choices: ['Choice 1', 'Choice 2'],
96
    };
97
    const pollCard = new PollCard(state, dummyLocalTimezone);
98
    const result = pollCard.choiceSection(0, 0);
99
    expect(result).toBeDefined();
100
    expect(result.widgets).toBeDefined();
101
    expect(result.widgets?.[0]?.decoratedText?.topLabel).toBeUndefined();
102
103
    // create choice section with the creator name (when added from new option)
104
    const result2 = pollCard.choiceSection(1, 0, 'Ahmad');
105
    expect(result2).toBeDefined();
106
    expect(result2.widgets?.[0]?.decoratedText?.topLabel).toEqual('Added by Ahmad');
107
  });
108
109
  it('build vote card with dummy state', () => {
110
    const pollCard = new PollCard(dummyPollState, dummyLocalTimezone).createCardWithId();
111
    expect(pollCard.card).toEqual(voteCardJson);
112
  });
113
114
  it('if closedTime > now, it should show a clock icon which indicate that poll has autoClose schedule', () => {
115
    const pollCard = new PollCard(dummyAutoclosePollState, dummyLocalTimezone).create();
116
    expect(pollCard.sections.find((section) => section.widgets?.[0]?.decoratedText?.startIcon?.knownIcon === 'CLOCK')).
117
      toBeDefined();
118
  });
119
120
  it('if poll has autoClose schedule but has invalid timezone the icon is not showed', () => {
121
    const pollCard = new PollCard(dummyAutoclosePollState, {
122
      id: 'Invalid/Timezone',
123
      offset: 25200000,
124
      locale: 'en-US',
125
    }).create();
126
    expect(pollCard.sections.find((section) => section.widgets?.[0]?.decoratedText?.startIcon?.knownIcon === 'CLOCK')).
127
      toBeUndefined();
128
  });
129
});
130