mirror of
https://github.com/LightZirconite/Microsoft-Rewards-Bot.git
synced 2026-01-11 01:36:16 +00:00
feature: Update the version to 2.60.0 and improve the handling of human gestures, etc.
This commit is contained in:
@@ -14,12 +14,12 @@ test('MobileFlow module exports correctly', async () => {
|
||||
|
||||
test('MobileFlow has run method', async () => {
|
||||
const { MobileFlow } = await import('../../src/flows/MobileFlow')
|
||||
|
||||
|
||||
// Mock bot instance
|
||||
const mockBot = {
|
||||
log: () => {},
|
||||
log: () => { },
|
||||
isMobile: true,
|
||||
config: {
|
||||
config: {
|
||||
workers: {},
|
||||
runOnZeroPoints: false,
|
||||
searchSettings: { retryMobileSearchAmount: 0 }
|
||||
@@ -29,7 +29,7 @@ test('MobileFlow has run method', async () => {
|
||||
activities: {},
|
||||
compromisedModeActive: false
|
||||
}
|
||||
|
||||
|
||||
const flow = new MobileFlow(mockBot as never)
|
||||
assert.ok(flow, 'MobileFlow instance should be created')
|
||||
assert.equal(typeof flow.run, 'function', 'MobileFlow should have run() method')
|
||||
@@ -37,27 +37,27 @@ test('MobileFlow has run method', async () => {
|
||||
|
||||
test('MobileFlowResult interface has correct structure', async () => {
|
||||
const { MobileFlow } = await import('../../src/flows/MobileFlow')
|
||||
|
||||
|
||||
// Validate that MobileFlowResult type exports (compile-time check)
|
||||
type MobileFlowResult = Awaited<ReturnType<InstanceType<typeof MobileFlow>['run']>>
|
||||
|
||||
|
||||
const mockResult: MobileFlowResult = {
|
||||
initialPoints: 1000,
|
||||
collectedPoints: 30
|
||||
}
|
||||
|
||||
|
||||
assert.equal(typeof mockResult.initialPoints, 'number', 'initialPoints should be a number')
|
||||
assert.equal(typeof mockResult.collectedPoints, 'number', 'collectedPoints should be a number')
|
||||
})
|
||||
|
||||
test('MobileFlow accepts retry tracker', async () => {
|
||||
const { MobileFlow } = await import('../../src/flows/MobileFlow')
|
||||
const { MobileRetryTracker } = await import('../../src/util/MobileRetryTracker')
|
||||
|
||||
const { MobileRetryTracker } = await import('../../src/util/state/MobileRetryTracker')
|
||||
|
||||
const mockBot = {
|
||||
log: () => {},
|
||||
log: () => { },
|
||||
isMobile: true,
|
||||
config: {
|
||||
config: {
|
||||
workers: {},
|
||||
runOnZeroPoints: false,
|
||||
searchSettings: { retryMobileSearchAmount: 3 }
|
||||
@@ -67,10 +67,10 @@ test('MobileFlow accepts retry tracker', async () => {
|
||||
activities: {},
|
||||
compromisedModeActive: false
|
||||
}
|
||||
|
||||
|
||||
const flow = new MobileFlow(mockBot as never)
|
||||
const tracker = new MobileRetryTracker(3)
|
||||
|
||||
|
||||
assert.ok(flow, 'MobileFlow should accept retry tracker')
|
||||
assert.equal(typeof tracker.registerFailure, 'function', 'MobileRetryTracker should have registerFailure method')
|
||||
})
|
||||
|
||||
@@ -14,40 +14,57 @@ test('SummaryReporter module exports correctly', async () => {
|
||||
|
||||
test('SummaryReporter creates instance with config', async () => {
|
||||
const { SummaryReporter } = await import('../../src/flows/SummaryReporter')
|
||||
|
||||
|
||||
const mockConfig = {
|
||||
webhook: { enabled: false },
|
||||
ntfy: { enabled: false },
|
||||
sessionPath: './sessions',
|
||||
jobState: { enabled: false }
|
||||
}
|
||||
|
||||
|
||||
const reporter = new SummaryReporter(mockConfig as never)
|
||||
assert.ok(reporter, 'SummaryReporter instance should be created')
|
||||
})
|
||||
|
||||
test('SummaryReporter creates summary correctly', async () => {
|
||||
const { SummaryReporter } = await import('../../src/flows/SummaryReporter')
|
||||
|
||||
|
||||
const mockConfig = {
|
||||
webhook: { enabled: false },
|
||||
ntfy: { enabled: false },
|
||||
sessionPath: './sessions',
|
||||
jobState: { enabled: false }
|
||||
}
|
||||
|
||||
|
||||
const reporter = new SummaryReporter(mockConfig as never)
|
||||
|
||||
|
||||
const accounts = [
|
||||
{ email: 'test@example.com', pointsEarned: 100, runDuration: 60000 },
|
||||
{ email: 'test2@example.com', pointsEarned: 150, runDuration: 70000, errors: ['test error'] }
|
||||
{
|
||||
email: 'test@example.com',
|
||||
pointsEarned: 100,
|
||||
runDuration: 60000,
|
||||
initialPoints: 1000,
|
||||
finalPoints: 1100,
|
||||
desktopPoints: 60,
|
||||
mobilePoints: 40
|
||||
},
|
||||
{
|
||||
email: 'test2@example.com',
|
||||
pointsEarned: 150,
|
||||
runDuration: 70000,
|
||||
initialPoints: 2000,
|
||||
finalPoints: 2150,
|
||||
desktopPoints: 90,
|
||||
mobilePoints: 60,
|
||||
errors: ['test error']
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
const startTime = new Date('2025-01-01T10:00:00Z')
|
||||
const endTime = new Date('2025-01-01T10:05:00Z')
|
||||
|
||||
|
||||
const summary = reporter.createSummary(accounts, startTime, endTime)
|
||||
|
||||
|
||||
assert.equal(summary.totalPoints, 250, 'Total points should be 250')
|
||||
assert.equal(summary.successCount, 1, 'Success count should be 1')
|
||||
assert.equal(summary.failureCount, 1, 'Failure count should be 1')
|
||||
@@ -56,22 +73,30 @@ test('SummaryReporter creates summary correctly', async () => {
|
||||
|
||||
test('SummaryData structure is correct', async () => {
|
||||
const { SummaryReporter } = await import('../../src/flows/SummaryReporter')
|
||||
|
||||
|
||||
const mockConfig = {
|
||||
webhook: { enabled: false },
|
||||
ntfy: { enabled: false },
|
||||
sessionPath: './sessions',
|
||||
jobState: { enabled: false }
|
||||
}
|
||||
|
||||
|
||||
const reporter = new SummaryReporter(mockConfig as never)
|
||||
|
||||
|
||||
const summary = reporter.createSummary(
|
||||
[{ email: 'test@example.com', pointsEarned: 50, runDuration: 30000 }],
|
||||
[{
|
||||
email: 'test@example.com',
|
||||
pointsEarned: 50,
|
||||
runDuration: 30000,
|
||||
initialPoints: 500,
|
||||
finalPoints: 550,
|
||||
desktopPoints: 30,
|
||||
mobilePoints: 20
|
||||
}],
|
||||
new Date(),
|
||||
new Date()
|
||||
)
|
||||
|
||||
|
||||
assert.ok(summary.startTime instanceof Date, 'startTime should be a Date')
|
||||
assert.ok(summary.endTime instanceof Date, 'endTime should be a Date')
|
||||
assert.equal(typeof summary.totalPoints, 'number', 'totalPoints should be a number')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import { LoginState, LoginStateDetector } from '../src/util/LoginStateDetector'
|
||||
import { LoginState, LoginStateDetector } from '../src/util/validation/LoginStateDetector'
|
||||
|
||||
/**
|
||||
* Tests for LoginStateDetector - login flow state machine
|
||||
@@ -10,6 +10,8 @@ import { LoginState, LoginStateDetector } from '../src/util/LoginStateDetector'
|
||||
// Type helper for mock Page objects in tests
|
||||
type MockPage = Parameters<typeof LoginStateDetector.detectState>[0]
|
||||
|
||||
const asMockPage = <T>(page: T): MockPage => page as unknown as MockPage
|
||||
|
||||
test('LoginState enum contains expected states', () => {
|
||||
assert.ok(LoginState.EmailPage, 'Should have EmailPage state')
|
||||
assert.ok(LoginState.PasswordPage, 'Should have PasswordPage state')
|
||||
@@ -60,7 +62,7 @@ test('detectState identifies LoggedIn state on rewards domain', async () => {
|
||||
evaluate: () => Promise.resolve(200)
|
||||
}
|
||||
|
||||
const detection = await LoginStateDetector.detectState(mockPage as MockPage)
|
||||
const detection = await LoginStateDetector.detectState(asMockPage(mockPage))
|
||||
|
||||
assert.equal(detection.state, LoginState.LoggedIn, 'Should detect LoggedIn state')
|
||||
assert.equal(detection.confidence, 'high', 'Should have high confidence')
|
||||
@@ -88,7 +90,7 @@ test('detectState identifies EmailPage state on login.live.com', async () => {
|
||||
evaluate: () => Promise.resolve(100)
|
||||
}
|
||||
|
||||
const detection = await LoginStateDetector.detectState(mockPage as MockPage)
|
||||
const detection = await LoginStateDetector.detectState(asMockPage(mockPage))
|
||||
|
||||
assert.equal(detection.state, LoginState.EmailPage, 'Should detect EmailPage state')
|
||||
assert.equal(detection.confidence, 'high', 'Should have high confidence')
|
||||
@@ -115,7 +117,7 @@ test('detectState identifies PasswordPage state', async () => {
|
||||
evaluate: () => Promise.resolve(100)
|
||||
}
|
||||
|
||||
const detection = await LoginStateDetector.detectState(mockPage as MockPage)
|
||||
const detection = await LoginStateDetector.detectState(asMockPage(mockPage))
|
||||
|
||||
assert.equal(detection.state, LoginState.PasswordPage, 'Should detect PasswordPage state')
|
||||
assert.equal(detection.confidence, 'high', 'Should have high confidence')
|
||||
@@ -142,7 +144,7 @@ test('detectState identifies TwoFactorRequired state', async () => {
|
||||
evaluate: () => Promise.resolve(100)
|
||||
}
|
||||
|
||||
const detection = await LoginStateDetector.detectState(mockPage as MockPage)
|
||||
const detection = await LoginStateDetector.detectState(asMockPage(mockPage))
|
||||
|
||||
assert.equal(detection.state, LoginState.TwoFactorRequired, 'Should detect TwoFactorRequired state')
|
||||
assert.equal(detection.confidence, 'high', 'Should have high confidence')
|
||||
@@ -170,7 +172,7 @@ test('detectState identifies PasskeyPrompt state', async () => {
|
||||
evaluate: () => Promise.resolve(100)
|
||||
}
|
||||
|
||||
const detection = await LoginStateDetector.detectState(mockPage as MockPage)
|
||||
const detection = await LoginStateDetector.detectState(asMockPage(mockPage))
|
||||
|
||||
assert.equal(detection.state, LoginState.PasskeyPrompt, 'Should detect PasskeyPrompt state')
|
||||
assert.equal(detection.confidence, 'high', 'Should have high confidence')
|
||||
@@ -198,7 +200,7 @@ test('detectState identifies Blocked state', async () => {
|
||||
evaluate: () => Promise.resolve(100)
|
||||
}
|
||||
|
||||
const detection = await LoginStateDetector.detectState(mockPage as MockPage)
|
||||
const detection = await LoginStateDetector.detectState(asMockPage(mockPage))
|
||||
|
||||
assert.equal(detection.state, LoginState.Blocked, 'Should detect Blocked state')
|
||||
assert.equal(detection.confidence, 'high', 'Should have high confidence')
|
||||
@@ -216,7 +218,7 @@ test('detectState returns Unknown for ambiguous pages', async () => {
|
||||
evaluate: () => Promise.resolve(50)
|
||||
}
|
||||
|
||||
const detection = await LoginStateDetector.detectState(mockPage as MockPage)
|
||||
const detection = await LoginStateDetector.detectState(asMockPage(mockPage))
|
||||
|
||||
assert.equal(detection.state, LoginState.Unknown, 'Should return Unknown for ambiguous pages')
|
||||
assert.equal(detection.confidence, 'low', 'Should have low confidence')
|
||||
@@ -234,7 +236,7 @@ test('detectState handles errors gracefully', async () => {
|
||||
}
|
||||
|
||||
try {
|
||||
await LoginStateDetector.detectState(mockPage as MockPage)
|
||||
await LoginStateDetector.detectState(asMockPage(mockPage))
|
||||
assert.fail('Should throw error')
|
||||
} catch (e) {
|
||||
assert.ok(e instanceof Error, 'Should throw Error instance')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import { MobileRetryTracker } from '../src/util/MobileRetryTracker'
|
||||
import { MobileRetryTracker } from '../src/util/state/MobileRetryTracker'
|
||||
|
||||
test('MobileRetryTracker stops retries after configured limit', () => {
|
||||
const tracker = new MobileRetryTracker(2)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import { QueryDiversityEngine } from '../src/util/QueryDiversityEngine'
|
||||
import { QueryDiversityEngine } from '../src/util/network/QueryDiversityEngine'
|
||||
|
||||
test('QueryDiversityEngine fetches and limits queries', async () => {
|
||||
const engine = new QueryDiversityEngine({
|
||||
@@ -13,7 +13,7 @@ test('QueryDiversityEngine fetches and limits queries', async () => {
|
||||
|
||||
assert.ok(queries.length > 0, 'Should return at least one query')
|
||||
assert.ok(queries.length <= 10, 'Should respect count limit')
|
||||
assert.ok(queries.every(q => typeof q === 'string' && q.length > 0), 'All queries should be non-empty strings')
|
||||
assert.ok(queries.every((q: string) => typeof q === 'string' && q.length > 0), 'All queries should be non-empty strings')
|
||||
})
|
||||
|
||||
test('QueryDiversityEngine deduplicates queries', async () => {
|
||||
|
||||
@@ -3,18 +3,8 @@
|
||||
* Tests intelligent page readiness and element detection
|
||||
*/
|
||||
|
||||
import assert from 'node:assert'
|
||||
import { describe, it } from 'node:test'
|
||||
|
||||
// Mock Playwright types for testing
|
||||
type MockPage = {
|
||||
url: () => string
|
||||
content: () => Promise<string>
|
||||
waitForLoadState: (state: string, options?: { timeout: number }) => Promise<void>
|
||||
waitForTimeout: (ms: number) => Promise<void>
|
||||
locator: (selector: string) => MockLocator
|
||||
evaluate: <T>(fn: () => T) => Promise<T>
|
||||
}
|
||||
import assert from 'node:assert';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
type MockLocator = {
|
||||
waitFor: (options: { state: string; timeout: number }) => Promise<void>
|
||||
@@ -94,7 +84,7 @@ describe('SmartWait', () => {
|
||||
mockLogFn('✓ Element found quickly (567ms)')
|
||||
|
||||
assert.strictEqual(logs.length, 2, 'Should capture log messages')
|
||||
assert.ok(logs[0].includes('1234ms'), 'Should include timing data')
|
||||
assert.ok(logs[0]?.includes('1234ms'), 'Should include timing data')
|
||||
})
|
||||
|
||||
it('should extract performance metrics from logs', () => {
|
||||
@@ -102,8 +92,8 @@ describe('SmartWait', () => {
|
||||
const timeMatch = logMessage.match(/(\d+)ms/)
|
||||
|
||||
assert.ok(timeMatch, 'Should include parseable timing')
|
||||
if (timeMatch) {
|
||||
const time = parseInt(timeMatch[1])
|
||||
if (timeMatch && timeMatch[1]) {
|
||||
const time = parseInt(timeMatch[1], 10)
|
||||
assert.ok(time > 0, 'Should extract valid timing')
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user