Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions achievements/achievements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,33 @@ const achievements: Achievement[] = [
condition: '週間起床ランキングで満点を獲得する',
category: 'sushi-bot',
},
{
id: 'asa-week-repdigit-1',
difficulty: 'hard',
title: '起床フィーバータイム',
condition: '週間起床ランキングでゾロ目である3桁の得点を獲得する',
category: 'sushi-bot',
counter: 'asa-week-repdigit',
value: 1,
},
{
id: 'asa-week-power-of-two-1',
difficulty: 'hard',
title: '起床ロボット',
condition: '週間起床ランキングで2の冪乗数の得点を獲得する',
category: 'sushi-bot',
counter: 'asa-week-power-of-two',
value: 1,
},
{
id: 'asa-week-334-1',
difficulty: 'hard',
title: 'なんでや',
condition: '週間起床ランキングで334点を獲得する',
category: 'sushi-bot',
counter: 'asa-week-334',
value: 1,
},
{
id: 'first-exercise',
difficulty: 'easy',
Expand Down
102 changes: 102 additions & 0 deletions sushi-bot/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import moment from 'moment';
import schedule, {Job, JobCallback} from 'node-schedule';
import {unlock, increment} from '../achievements';
import State from '../lib/state';
import {MockedStateInterface} from '../lib/__mocks__/state';
import sushi from './index.js';
import Slack from '../lib/slackMock';

vi.mock('../achievements');
vi.mock('moment');
vi.mock('../lib/state');
vi.mock('node-schedule', () => ({
default: {
scheduleJob: vi.fn(),
},
scheduleJob: vi.fn(),
}));
vi.mock('fs-extra', () => ({
mkdirp: vi.fn(),
readFile: vi.fn(() => Promise.resolve(Buffer.from(''))),
Expand All @@ -13,11 +23,18 @@
}));

let slack: InstanceType<typeof Slack> = null;
let scheduleCallback: JobCallback | null = null;

describe('sushi-bot', async () => {
const originalMoment = (await vi.importActual<{default: typeof import('moment')}>('moment')).default;

beforeEach(async () => {
vi.clearAllMocks();
scheduleCallback = null;
vi.mocked(schedule.scheduleJob).mockImplementation((rule, fn) => {
scheduleCallback = fn;
return {} as Job;
});
slack = new Slack();
await sushi(slack);

Expand Down Expand Up @@ -464,4 +481,89 @@
ts: slack.fakeTimestamp,
});
}));

describe('weekly wakeup ranking achievements', () => {
beforeEach(() => {
vi.mocked(slack.webClient.users.list).mockResolvedValue({
ok: true,
members: [
{
id: slack.fakeUser,
name: 'fakeUser',
profile: {
display_name: 'Fake User',
image_24: 'https://example.com/image.png',
},
},
],
});
});

it('unlocks "起床フィーバータイム" (asa-week-repdigit) when score is a 3-digit repdigit (e.g. 333)', async () => {

Check warning on line 502 in sushi-bot/index.test.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace these 3 tests with a single Parameterized one.

See more on https://sonarcloud.io/project/issues?id=tsg-ut_slackbot&issues=AZ_qP83tU0-DRbDEqVRs&open=AZ_qP83tU0-DRbDEqVRs&pullRequest=1244
const mockedState = State as MockedStateInterface<any>;
const state = mockedState.mocks.get('sushi-bot-counter-asa');
state.data = {[slack.fakeUser]: 333};

expect(scheduleCallback).not.toBeNull();
// 2023-01-01 is a Sunday!
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));

expect(increment).toHaveBeenCalledWith(slack.fakeUser, 'asa-week-repdigit');
});

it('does not unlock "起床フィーバータイム" when score is not a 3-digit repdigit (e.g. 334)', async () => {

Check warning on line 514 in sushi-bot/index.test.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace these 3 tests with a single Parameterized one.

See more on https://sonarcloud.io/project/issues?id=tsg-ut_slackbot&issues=AZ_qP83tU0-DRbDEqVRt&open=AZ_qP83tU0-DRbDEqVRt&pullRequest=1244
const mockedState = State as MockedStateInterface<any>;
const state = mockedState.mocks.get('sushi-bot-counter-asa');
state.data = {[slack.fakeUser]: 334};

expect(scheduleCallback).not.toBeNull();
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));

expect(increment).not.toHaveBeenCalledWith(slack.fakeUser, 'asa-week-repdigit');
});

it('unlocks "起床ロボット" (asa-week-power-of-two) when score is a power of 2 (e.g. 256)', async () => {
const mockedState = State as MockedStateInterface<any>;
const state = mockedState.mocks.get('sushi-bot-counter-asa');
state.data = {[slack.fakeUser]: 256};

expect(scheduleCallback).not.toBeNull();
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));

expect(increment).toHaveBeenCalledWith(slack.fakeUser, 'asa-week-power-of-two');
});

it('does not unlock "起床ロボット" when score is not a power of 2 (e.g. 255)', async () => {
const mockedState = State as MockedStateInterface<any>;
const state = mockedState.mocks.get('sushi-bot-counter-asa');
state.data = {[slack.fakeUser]: 255};

expect(scheduleCallback).not.toBeNull();
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));

expect(increment).not.toHaveBeenCalledWith(slack.fakeUser, 'asa-week-power-of-two');
});

it('unlocks "なんでや" (asa-week-334) when score is exactly 334', async () => {
const mockedState = State as MockedStateInterface<any>;
const state = mockedState.mocks.get('sushi-bot-counter-asa');
state.data = {[slack.fakeUser]: 334};

expect(scheduleCallback).not.toBeNull();
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));

expect(increment).toHaveBeenCalledWith(slack.fakeUser, 'asa-week-334');
});

it('does not unlock "なんでや" when score is not exactly 334 (e.g. 333)', async () => {
const mockedState = State as MockedStateInterface<any>;
const state = mockedState.mocks.get('sushi-bot-counter-asa');
state.data = {[slack.fakeUser]: 333};

expect(scheduleCallback).not.toBeNull();
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));

expect(increment).not.toHaveBeenCalledWith(slack.fakeUser, 'asa-week-334');
});
});
});
9 changes: 9 additions & 0 deletions sushi-bot/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,15 @@ export default async function ({eventClient, webClient: slack}: SlackInterface)
if (count >= 7 * 108) {
unlock(user, 'asa-week-perfect');
}
if (count >= 100 && count <= 999 && count % 111 === 0) {
increment(user, 'asa-week-repdigit');
}
if (count > 0 && (count & (count - 1)) === 0) {
increment(user, 'asa-week-power-of-two');
}
if (count === 334) {
increment(user, 'asa-week-334');
}

return {
author_name: `${index + 1}位: ${name} (${count}点)`,
Expand Down
Loading