mirror of
https://github.com/Ujwal223/FocusGram.git
synced 2026-07-02 17:35:46 +02:00
Feature Pack with bug fixes for V2
This commit is contained in:
@@ -14,11 +14,9 @@ void main() {
|
||||
final service = AppLockService();
|
||||
await service.init();
|
||||
|
||||
// Set a PIN first
|
||||
await service.setPin('1234', forAppWide: true);
|
||||
|
||||
// Verify it
|
||||
final valid = await service.verifyPin('1234');
|
||||
final valid = await service.verifyPin('1234', forAppWide: true);
|
||||
expect(valid, isTrue);
|
||||
});
|
||||
|
||||
@@ -28,7 +26,7 @@ void main() {
|
||||
|
||||
await service.setPin('1234', forAppWide: true);
|
||||
|
||||
final valid = await service.verifyPin('0000');
|
||||
final valid = await service.verifyPin('0000', forAppWide: true);
|
||||
expect(valid, isFalse);
|
||||
});
|
||||
|
||||
@@ -36,10 +34,8 @@ void main() {
|
||||
final service = AppLockService();
|
||||
await service.init();
|
||||
|
||||
// Set messages PIN
|
||||
await service.setPin('5678', forAppWide: false);
|
||||
|
||||
// Verify with forAppWide: false (messages PIN)
|
||||
final valid = await service.verifyPin('5678', forAppWide: false);
|
||||
expect(valid, isTrue);
|
||||
});
|
||||
@@ -49,7 +45,7 @@ void main() {
|
||||
await service.init();
|
||||
|
||||
await service.setPin('1234', forAppWide: true);
|
||||
await service.onBackgrounded();
|
||||
service.onBackgrounded();
|
||||
expect(service.shouldLockOnResume, isTrue);
|
||||
|
||||
service.onUnlocked();
|
||||
@@ -73,7 +69,7 @@ void main() {
|
||||
final service = AppLockService();
|
||||
await service.init();
|
||||
|
||||
final valid = await service.verifyPin('1234');
|
||||
final valid = await service.verifyPin('1234', forAppWide: true);
|
||||
expect(valid, isFalse);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,20 +5,22 @@ import 'package:focusgram/scripts/focus_scripts.dart';
|
||||
|
||||
void main() {
|
||||
group('FocusSettings — Field cleanup', () {
|
||||
test('only ghostMode remains (fullDmGhost and storyGhost removed)',
|
||||
() async {
|
||||
const settings = FocusSettings(ghostMode: true);
|
||||
test(
|
||||
'only ghostMode remains (fullDmGhost and storyGhost removed)',
|
||||
() async {
|
||||
const settings = FocusSettings(ghostMode: true);
|
||||
|
||||
expect(settings.ghostMode, isTrue);
|
||||
expect(settings.noAds, isTrue);
|
||||
expect(settings.noStories, isFalse);
|
||||
expect(settings.noReels, isFalse);
|
||||
expect(settings.noAutoplay, isFalse);
|
||||
expect(settings.noDMs, isFalse);
|
||||
expect(settings.ghostMode, isTrue);
|
||||
expect(settings.noAds, isTrue);
|
||||
expect(settings.noStories, isFalse);
|
||||
expect(settings.noReels, isFalse);
|
||||
expect(settings.noAutoplay, isFalse);
|
||||
expect(settings.noDMs, isFalse);
|
||||
|
||||
// Verify fullDmGhost and storyGhost are NOT fields anymore
|
||||
// (these would be compile errors if they existed)
|
||||
});
|
||||
// Verify fullDmGhost and storyGhost are NOT fields anymore
|
||||
// (these would be compile errors if they existed)
|
||||
},
|
||||
);
|
||||
|
||||
test('default ghostMode is false', () async {
|
||||
const settings = FocusSettings();
|
||||
@@ -48,13 +50,12 @@ void main() {
|
||||
});
|
||||
|
||||
test('does NOT inject ghost scripts when ghostMode is false', () async {
|
||||
final scripts =
|
||||
buildUserScripts(const FocusSettings(ghostMode: false));
|
||||
final scripts = buildUserScripts(const FocusSettings(ghostMode: false));
|
||||
|
||||
// Should have no DOCUMENT_START scripts
|
||||
final startScripts =
|
||||
scripts.where((s) =>
|
||||
s.injectionTime == UserScriptInjectionTime.AT_DOCUMENT_START);
|
||||
final startScripts = scripts.where(
|
||||
(s) => s.injectionTime == UserScriptInjectionTime.AT_DOCUMENT_START,
|
||||
);
|
||||
for (final s in startScripts) {
|
||||
expect(s.source.contains('__fgFullDmGhost'), isFalse);
|
||||
}
|
||||
@@ -65,28 +66,28 @@ void main() {
|
||||
const FocusSettings(ghostMode: true, noAutoplay: true),
|
||||
);
|
||||
|
||||
final startScripts =
|
||||
scripts.where((s) =>
|
||||
s.injectionTime == UserScriptInjectionTime.AT_DOCUMENT_START);
|
||||
final startScripts = scripts.where(
|
||||
(s) => s.injectionTime == UserScriptInjectionTime.AT_DOCUMENT_START,
|
||||
);
|
||||
expect(startScripts.length, equals(1));
|
||||
expect(startScripts.first.source, contains('__fgFullDmGhost=true'));
|
||||
expect(startScripts.first.source, contains('document.addEventListener'));
|
||||
});
|
||||
|
||||
test('injects hideStoryTray at DOCUMENT_END when noStories is true',
|
||||
() async {
|
||||
final scripts = buildUserScripts(
|
||||
const FocusSettings(noStories: true),
|
||||
);
|
||||
test(
|
||||
'injects hideStoryTray at DOCUMENT_END when noStories is true',
|
||||
() async {
|
||||
final scripts = buildUserScripts(const FocusSettings(noStories: true));
|
||||
|
||||
final endScripts =
|
||||
scripts.where((s) =>
|
||||
s.injectionTime == UserScriptInjectionTime.AT_DOCUMENT_END);
|
||||
expect(endScripts.length, equals(1));
|
||||
expect(
|
||||
endScripts.first.source,
|
||||
contains('[data-pagelet="story_tray"]'),
|
||||
);
|
||||
});
|
||||
final endScripts = scripts.where(
|
||||
(s) => s.injectionTime == UserScriptInjectionTime.AT_DOCUMENT_END,
|
||||
);
|
||||
expect(endScripts.length, equals(1));
|
||||
expect(
|
||||
endScripts.first.source,
|
||||
contains('[data-pagelet="story_tray"]'),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,20 +5,22 @@ import 'package:focusgram/scripts/focus_scripts.dart';
|
||||
|
||||
void main() {
|
||||
group('FocusSettings — Field cleanup', () {
|
||||
test('only ghostMode remains (fullDmGhost and storyGhost removed)',
|
||||
() async {
|
||||
const settings = FocusSettings(ghostMode: true);
|
||||
test(
|
||||
'only ghostMode remains (fullDmGhost and storyGhost removed)',
|
||||
() async {
|
||||
const settings = FocusSettings(ghostMode: true);
|
||||
|
||||
expect(settings.ghostMode, isTrue);
|
||||
expect(settings.noAds, isTrue);
|
||||
expect(settings.noStories, isFalse);
|
||||
expect(settings.noReels, isFalse);
|
||||
expect(settings.noAutoplay, isFalse);
|
||||
expect(settings.noDMs, isFalse);
|
||||
expect(settings.ghostMode, isTrue);
|
||||
expect(settings.noAds, isTrue);
|
||||
expect(settings.noStories, isFalse);
|
||||
expect(settings.noReels, isFalse);
|
||||
expect(settings.noAutoplay, isFalse);
|
||||
expect(settings.noDMs, isFalse);
|
||||
|
||||
// Verify fullDmGhost and storyGhost are NOT fields anymore
|
||||
// (these would be compile errors if they existed)
|
||||
});
|
||||
// Verify fullDmGhost and storyGhost are NOT fields anymore
|
||||
// (these would be compile errors if they existed)
|
||||
},
|
||||
);
|
||||
|
||||
test('default ghostMode is false', () async {
|
||||
const settings = FocusSettings();
|
||||
@@ -43,8 +45,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('does NOT inject ghost scripts when ghostMode is false', () async {
|
||||
final scripts =
|
||||
buildUserScripts(const FocusSettings(ghostMode: false));
|
||||
final scripts = buildUserScripts(const FocusSettings(ghostMode: false));
|
||||
|
||||
// Should have no start scripts (ghostMode is the only start-level script)
|
||||
// unless other features like noAutoplay are also false
|
||||
@@ -62,9 +63,9 @@ void main() {
|
||||
);
|
||||
|
||||
// Should have 1 DOCUMENT_START script combining ghost + autoplay
|
||||
final startScripts =
|
||||
scripts.where((s) =>
|
||||
s.injectionTime == UserScriptInjectionTime.AT_DOCUMENT_START);
|
||||
final startScripts = scripts.where(
|
||||
(s) => s.injectionTime == UserScriptInjectionTime.AT_DOCUMENT_START,
|
||||
);
|
||||
expect(startScripts.length, equals(1));
|
||||
expect(startScripts.first.source, contains('__fgFullDmGhost=true'));
|
||||
expect(startScripts.first.source, contains('document.addEventListener'));
|
||||
|
||||
@@ -68,11 +68,13 @@ void main() {
|
||||
expect(s.isGrayscaleActiveNow, isTrue);
|
||||
});
|
||||
|
||||
test('isGrayscaleActiveNow returns false when toggle off and no schedules',
|
||||
() async {
|
||||
final s = SettingsService();
|
||||
await s.init();
|
||||
expect(s.isGrayscaleActiveNow, isFalse);
|
||||
});
|
||||
test(
|
||||
'isGrayscaleActiveNow returns false when toggle off and no schedules',
|
||||
() async {
|
||||
final s = SettingsService();
|
||||
await s.init();
|
||||
expect(s.isGrayscaleActiveNow, isFalse);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -105,14 +105,17 @@ void main() {
|
||||
});
|
||||
|
||||
// ── Ephemeral / visual seen ───────────────────────────────
|
||||
test('blocks /api/v1/direct_v2/threads/{id}/items/{id}/mark_visual_item_seen/', () {
|
||||
expect(
|
||||
seenPattern.hasMatch(
|
||||
'https://www.instagram.com/api/v1/direct_v2/threads/abc/items/def/mark_visual_item_seen/',
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
test(
|
||||
'blocks /api/v1/direct_v2/threads/{id}/items/{id}/mark_visual_item_seen/',
|
||||
() {
|
||||
expect(
|
||||
seenPattern.hasMatch(
|
||||
'https://www.instagram.com/api/v1/direct_v2/threads/abc/items/def/mark_visual_item_seen/',
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test('blocks /api/v1/direct_v2/visual_thread/{id}/seen/', () {
|
||||
expect(
|
||||
@@ -171,18 +174,14 @@ void main() {
|
||||
|
||||
test('blocks /api/v1/launcher/sync/', () {
|
||||
expect(
|
||||
seenPattern.hasMatch(
|
||||
'https://www.instagram.com/api/v1/launcher/sync/',
|
||||
),
|
||||
seenPattern.hasMatch('https://www.instagram.com/api/v1/launcher/sync/'),
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
|
||||
test('blocks /api/v1/logging/', () {
|
||||
expect(
|
||||
seenPattern.hasMatch(
|
||||
'https://www.instagram.com/api/v1/logging/event',
|
||||
),
|
||||
seenPattern.hasMatch('https://www.instagram.com/api/v1/logging/event'),
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
@@ -204,10 +203,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('blocks /ajax/bz', () {
|
||||
expect(
|
||||
seenPattern.hasMatch('https://www.instagram.com/ajax/bz'),
|
||||
isTrue,
|
||||
);
|
||||
expect(seenPattern.hasMatch('https://www.instagram.com/ajax/bz'), isTrue);
|
||||
});
|
||||
|
||||
test('blocks /ajax/logging/', () {
|
||||
@@ -220,18 +216,14 @@ void main() {
|
||||
// ── Should NOT block legitimate endpoints ─────────────────
|
||||
test('does NOT block normal feed timeline request', () {
|
||||
expect(
|
||||
seenPattern.hasMatch(
|
||||
'https://www.instagram.com/api/v1/feed/timeline/',
|
||||
),
|
||||
seenPattern.hasMatch('https://www.instagram.com/api/v1/feed/timeline/'),
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
test('does NOT block graphql queries', () {
|
||||
expect(
|
||||
seenPattern.hasMatch(
|
||||
'https://www.instagram.com/api/graphql',
|
||||
),
|
||||
seenPattern.hasMatch('https://www.instagram.com/api/graphql'),
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:focusgram/services/level_service.dart';
|
||||
|
||||
@@ -9,7 +8,6 @@ void main() {
|
||||
|
||||
setUp(() async {
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
// Ensure Hive is available for LevelService
|
||||
if (!Hive.isAdapterRegistered(0)) {
|
||||
await Hive.initFlutter();
|
||||
}
|
||||
@@ -17,13 +15,9 @@ void main() {
|
||||
|
||||
group('AppFeature — Your Journey unlock table', () {
|
||||
test('fullDmGhost is NOT in the all list', () async {
|
||||
// fullDmGhost should still be defined as a constant
|
||||
expect(AppFeature.fullDmGhost, isNotNull);
|
||||
|
||||
// But should NOT appear in the unlock table shown to users
|
||||
final contains = AppFeature.all.any(
|
||||
(f) => f.id == 'full_dm_ghost',
|
||||
);
|
||||
final contains = AppFeature.all.any((f) => f.id == 'full_dm_ghost');
|
||||
expect(contains, isFalse);
|
||||
});
|
||||
|
||||
@@ -47,20 +41,12 @@ void main() {
|
||||
|
||||
group('LevelService — No Firestore dependency', () {
|
||||
test('init succeeds without Firestore (uses Hive only)', () async {
|
||||
// This would crash if init tried to reach Firestore
|
||||
// Since we removed Firebase, it should work with just Hive cache
|
||||
final levelService = LevelService();
|
||||
|
||||
// Should not throw — even if no Firestore is available
|
||||
await expectLater(
|
||||
() => levelService.init(),
|
||||
returnsNormally,
|
||||
);
|
||||
await expectLater(() => levelService.init(), returnsNormally);
|
||||
|
||||
// Default state
|
||||
expect(levelService.level, equals(1));
|
||||
expect(levelService.xp, equals(0));
|
||||
expect(levelService.synced, isFalse);
|
||||
});
|
||||
|
||||
test('addXpForAd awards XP without Firestore', () async {
|
||||
@@ -73,14 +59,13 @@ void main() {
|
||||
expect(levelService.adsWatchedTotal, equals(1));
|
||||
});
|
||||
|
||||
test('debugSetLevel works with Hive-only storage', () async {
|
||||
test('level progresses from XP', () async {
|
||||
final levelService = LevelService();
|
||||
await levelService.init();
|
||||
|
||||
await levelService.debugSetLevel(3, 300);
|
||||
|
||||
expect(levelService.level, equals(3));
|
||||
expect(levelService.xp, equals(300));
|
||||
expect(levelService.level, equals(1));
|
||||
expect(levelService.xp, equals(0));
|
||||
expect(levelService.levelProgress, equals(0.0));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -37,18 +37,20 @@ void main() {
|
||||
expect(sm.isSessionActive, isTrue);
|
||||
});
|
||||
|
||||
test('canExtendAppSession is false after re-ending an extended session',
|
||||
() async {
|
||||
final sm = SessionManager();
|
||||
await sm.init();
|
||||
test(
|
||||
'canExtendAppSession is false after re-ending an extended session',
|
||||
() async {
|
||||
final sm = SessionManager();
|
||||
await sm.init();
|
||||
|
||||
sm.startAppSession(60);
|
||||
sm.endAppSession();
|
||||
sm.extendAppSession();
|
||||
sm.endAppSession();
|
||||
sm.startAppSession(60);
|
||||
sm.endAppSession();
|
||||
sm.extendAppSession();
|
||||
sm.endAppSession();
|
||||
|
||||
expect(sm.canExtendAppSession, isFalse);
|
||||
});
|
||||
expect(sm.canExtendAppSession, isFalse);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
group('SessionManager — App session lifecycle', () {
|
||||
|
||||
Reference in New Issue
Block a user